Added FW-Yaml module for distributed-firewall network example.
This commit is contained in:
parent
1c4f2b260c
commit
fcd44c2b78
|
@ -0,0 +1,147 @@
|
|||
# Google Cloud VPC Firewall - Yaml
|
||||
|
||||
This module allows creation and management of different types of firewall rules by defining them in well formatted `yaml` files.
|
||||
|
||||
Yaml abstraction for FW rules can simplify users onboarding and also makes rules definition simpler and clearer comparing to HCL.
|
||||
|
||||
Nested folder structure for yaml configurations is supported, which allows better and structured code management.
|
||||
|
||||
## Example
|
||||
|
||||
### Terraform code
|
||||
|
||||
```hcl
|
||||
module "prod-firewall" {
|
||||
source = "./modules/net-vpc-firewall-yaml"
|
||||
project_id = "my-prod-project"
|
||||
network = "my-prod-network"
|
||||
config_path = "./production"
|
||||
log_config = {
|
||||
metadata = "INCLUDE_ALL_METADATA"
|
||||
}
|
||||
}
|
||||
|
||||
module "dev-firewall" {
|
||||
source = "./modules/net-vpc-firewall-yaml"
|
||||
project_id = "my-dev-project"
|
||||
network = "my-dev-network"
|
||||
config_path = "./development"
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration Structure
|
||||
|
||||
```bash
|
||||
├── development
|
||||
│ ├── core-network
|
||||
│ │ └── common-rules.yaml
|
||||
│ ├── team-a
|
||||
│ │ ├── databases.yaml
|
||||
│ │ └── webb-app-a.yaml
|
||||
│ └── team-b
|
||||
│ ├── backend.yaml
|
||||
│ └── frontend.yaml
|
||||
└── production
|
||||
├── core-network
|
||||
│ └── common-rules.yaml
|
||||
├── team-a
|
||||
│ ├── databases.yaml
|
||||
│ └── webb-app-a.yaml
|
||||
└── team-b
|
||||
├── backend.yaml
|
||||
└── frontend.yaml
|
||||
```
|
||||
|
||||
### Rule definition format and structure
|
||||
|
||||
Firewall rules configuration should be placed in a set of yaml files in a folder/s. Firewall rule entry structure is following:
|
||||
|
||||
```yaml
|
||||
rule-name: # descriptive name, naming convention is adjusted by the module
|
||||
allow: # `allow` or `deny`
|
||||
- ports: ['443', '80'] # ports for a specific protocol, keep empty list `[]` for all ports
|
||||
protocol: tcp # protocol, put `all` for any protocol
|
||||
direction: EGRESS # EGRESS or INGRESS
|
||||
disabled: false # `false` or `true`, FW rule is disabled when `true`, default value is `true`
|
||||
priority: 1000 # rule priority value, default value is 1000
|
||||
source_ranges: # list of source ranges, should be specified only for `INGRESS` rule
|
||||
- 0.0.0.0/0
|
||||
destination_ranges: # list of destination ranges, should be specified only for `EGRESS` rule
|
||||
- 0.0.0.0/0
|
||||
source_tags: ['some-tag'] # list of source tags, should be specified only for `INGRESS` rule
|
||||
source_service_accounts: # list of source service accounts, should be specified only for `INGRESS` rule, can not be specified together with `source_tags` or `target_tags`
|
||||
- myapp@myproject-id.iam.gserviceaccount.com
|
||||
target_tags: ['some-tag'] # list of target tags
|
||||
target_service_accounts: # list of target service accounts, , can not be specified together with `source_tags` or `target_tags`
|
||||
- myapp@myproject-id.iam.gserviceaccount.com
|
||||
```
|
||||
|
||||
|
||||
Firewall rules example yaml configuration
|
||||
|
||||
```bash
|
||||
cat ./production/core-network/common-rules.yaml
|
||||
# allow ingress from GCLB to all instances in the network
|
||||
lb-health-checks:
|
||||
allow:
|
||||
- ports: []
|
||||
protocol: tcp
|
||||
direction: INGRESS
|
||||
priority: 1001
|
||||
source_ranges:
|
||||
- 35.191.0.0/16
|
||||
- 130.211.0.0/22
|
||||
|
||||
# deny all eggress
|
||||
deny-all:
|
||||
deny:
|
||||
- ports: []
|
||||
protocol: all
|
||||
direction: EGRESS
|
||||
priority: 65535
|
||||
destination_ranges:
|
||||
- 0.0.0.0/0
|
||||
|
||||
cat ./development/team-a/web-app-a.yaml
|
||||
# Myapp egress
|
||||
web-app-a-egress:
|
||||
allow:
|
||||
- ports: [443]
|
||||
protocol: tcp
|
||||
direction: EGRESS
|
||||
destination_ranges:
|
||||
- 192.168.0.0/24
|
||||
target_service_accounts:
|
||||
- myapp@myproject-id.iam.gserviceaccount.com
|
||||
# Myapp ingress
|
||||
web-app-a-ingress:
|
||||
allow:
|
||||
- ports: [1234]
|
||||
protocol: tcp
|
||||
direction: INGRESS
|
||||
source_service_accounts:
|
||||
- frontend-sa@myproject-id.iam.gserviceaccount.com
|
||||
target_service_accounts:
|
||||
- web-app-a@myproject-id.iam.gserviceaccount.com
|
||||
```
|
||||
|
||||
<!-- BEGIN TFDOC -->
|
||||
## Variables
|
||||
|
||||
| name | description | type | required | default |
|
||||
|---|---|:---: |:---:|:---:|
|
||||
| config_path | Path to a folder where firewall configs are stored in yaml format. Folder may include subfolders with configuration files. Files suffix must be `.yaml` | <code title="">string</code> | ✓ | |
|
||||
| network | Name of the network this set of firewall rules applies to. | <code title="">string</code> | ✓ | |
|
||||
| project_id | Project Id. | <code title="">string</code> | ✓ | |
|
||||
| *log_config* | Log configuration. Possible values for `metadata` are `EXCLUDE_ALL_METADATA` and `INCLUDE_ALL_METADATA`. Set to `null` for disabling firewall logging. | <code title="object({ metadata = string })">object({...})</code> | | <code title="">null</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
| name | description | sensitive |
|
||||
|---|---|:---:|
|
||||
| egress_allow_rules | Egress rules with allow blocks. | |
|
||||
| egress_deny_rules | Egress rules with allow blocks. | |
|
||||
| ingress_allow_rules | Ingress rules with allow blocks. | |
|
||||
| ingress_deny_rules | Ingress rules with deny blocks. | |
|
||||
<!-- END TFDOC -->
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* Copyright 2021 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.
|
||||
*/
|
||||
|
||||
locals {
|
||||
firewall_rules = merge(
|
||||
[
|
||||
for config_file in fileset("${path.root}/${var.config_path}", "**/*.yaml") :
|
||||
try(yamldecode(file("${path.root}/${var.config_path}/${config_file}")), {})
|
||||
]...
|
||||
)
|
||||
}
|
||||
|
||||
resource "time_static" "timestamp" {
|
||||
for_each = local.firewall_rules
|
||||
triggers = {
|
||||
name = md5(jsonencode(each.value))
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_compute_firewall" "rules" {
|
||||
for_each = local.firewall_rules
|
||||
project = var.project_id
|
||||
name = format(
|
||||
"fwr-%s-%s-%s",
|
||||
(try(each.value.target_service_accounts, null) != null ? "sac" : try(each.value.target_tags, null) != null ? "vpc" : "all"),
|
||||
substr(lower(each.value.direction), 0, 1),
|
||||
each.key
|
||||
)
|
||||
description = format(
|
||||
"%s rule in network %s for %s created at %s",
|
||||
each.value.direction,
|
||||
var.network,
|
||||
each.key,
|
||||
time_static.timestamp[each.key].rfc3339
|
||||
)
|
||||
|
||||
network = var.network
|
||||
direction = each.value.direction
|
||||
priority = try(each.value.priority, 1000)
|
||||
disabled = try(each.value.disabled, null)
|
||||
|
||||
source_ranges = try(each.value.source_ranges, each.value.direction == "INGRESS" ? [] : null)
|
||||
source_tags = try(each.value.source_tags, null)
|
||||
source_service_accounts = try(each.value.source_service_accounts, null)
|
||||
|
||||
destination_ranges = try(each.value.destination_ranges, each.value.direction == "EGRESS" ? [] : null)
|
||||
target_tags = try(each.value.target_tags, null)
|
||||
target_service_accounts = try(each.value.target_service_accounts, null)
|
||||
|
||||
dynamic "allow" {
|
||||
for_each = { for block in try(each.value.allow, []) :
|
||||
"${block.protocol}-${join("-", block.ports)}" => {
|
||||
ports = [for port in block.ports : tostring(port)]
|
||||
protocol = block.protocol
|
||||
}
|
||||
}
|
||||
content {
|
||||
protocol = allow.value.protocol
|
||||
ports = allow.value.ports
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "deny" {
|
||||
for_each = { for block in try(each.value.deny, []) :
|
||||
"${block.protocol}-${join("-", block.ports)}" => {
|
||||
ports = [for port in block.ports : tostring(port)]
|
||||
protocol = block.protocol
|
||||
}
|
||||
}
|
||||
content {
|
||||
protocol = deny.value.protocol
|
||||
ports = deny.value.ports
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "log_config" {
|
||||
for_each = var.log_config != null ? [""] : []
|
||||
content {
|
||||
metadata = var.log_config.metadata
|
||||
}
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* Copyright 2021 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.
|
||||
*/
|
||||
|
||||
output "ingress_allow_rules" {
|
||||
description = "Ingress rules with allow blocks."
|
||||
value = [
|
||||
for rule in google_compute_firewall.rules :
|
||||
rule.name if rule.direction == "INGRESS" && length(rule.allow) > 0
|
||||
]
|
||||
}
|
||||
|
||||
output "ingress_deny_rules" {
|
||||
description = "Ingress rules with deny blocks."
|
||||
value = [
|
||||
for rule in google_compute_firewall.rules :
|
||||
rule.name if rule.direction == "INGRESS" && length(rule.deny) > 0
|
||||
]
|
||||
}
|
||||
|
||||
output "egress_allow_rules" {
|
||||
description = "Egress rules with allow blocks."
|
||||
value = [
|
||||
for rule in google_compute_firewall.rules :
|
||||
rule.name if rule.direction == "EGRESS" && length(rule.allow) > 0
|
||||
]
|
||||
}
|
||||
|
||||
output "egress_deny_rules" {
|
||||
description = "Egress rules with allow blocks."
|
||||
value = [
|
||||
for rule in google_compute_firewall.rules :
|
||||
rule.name if rule.direction == "EGRESS" && length(rule.deny) > 0
|
||||
]
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Copyright 2021 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.
|
||||
*/
|
||||
|
||||
variable "network" {
|
||||
description = "Name of the network this set of firewall rules applies to."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
description = "Project Id."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "config_path" {
|
||||
description = "Path to a folder where firewall configs are stored in yaml format. Folder may include subfolders with configuration files. Files suffix must be `.yaml`"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "log_config" {
|
||||
description = "Log configuration. Possible values for `metadata` are `EXCLUDE_ALL_METADATA` and `INCLUDE_ALL_METADATA`. Set to `null` for disabling firewall logging."
|
||||
type = object({
|
||||
metadata = string
|
||||
})
|
||||
default = null
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Copyright 2021 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.
|
||||
*/
|
||||
|
||||
|
||||
terraform {
|
||||
required_version = ">= 0.13.3"
|
||||
}
|
Loading…
Reference in New Issue