Skip to content

Commit

Permalink
Add support for iam_additive and simplify factory interface in net …
Browse files Browse the repository at this point in the history
…VPC module (#1259)

* initial implementation, no tests

* change interface, align tests

* add examples ToC

* fix variable type, test module-level variable
  • Loading branch information
ludoo authored and lcaggio committed May 5, 2023
1 parent a777822 commit b44b2eb
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 34 deletions.
49 changes: 33 additions & 16 deletions modules/net-vpc/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
# Minimalistic VPC module
# VPC module

This module allows creation and management of VPC networks including subnetworks and subnetwork IAM bindings, Shared VPC activation and service project registration, and one-to-one peering.
This module allows creation and management of VPC networks including subnetworks and subnetwork IAM bindings, and most features and options related to VPCs and subnets.

## Examples

The module allows for several different VPC configurations, some of the most common are shown below.
- [Simple VPC](#simple-vpc)
- [Subnet Options](#subnet-options)
- [Subnet IAM](#subnet-iam)
- [Peering](#peering)
- [Shared VPC](#shared-vpc)
- [Private Service Networking](#private-service-networking)
- [Private Service Networking with Peering Routes](#private-service-networking-with-peering-routes)
- [Subnets for Private Service Connect, Proxy-only subnets](#subnets-for-private-service-connect-proxy-only-subnets)
- [DNS Policies](#dns-policies)
- [Subnet Factory](#subnet-factory)
- [Custom Routes](#custom-routes)

### Simple VPC

Expand Down Expand Up @@ -105,14 +115,16 @@ module "vpc" {
"user:[email protected]", "group:[email protected]"
]
}
}
subnet_iam_additive = {
"europe-west1/subnet-2" = {
"roles/compute.networkUser" = [
"user:[email protected]", "group:[email protected]"
]
}
}
}
# tftest modules=1 resources=5 inventory=subnet-iam.yaml
# tftest modules=1 resources=6 inventory=subnet-iam.yaml
```

### Peering
Expand Down Expand Up @@ -315,7 +327,7 @@ module "vpc" {
name = "my-network"
data_folder = "config/subnets"
}
# tftest modules=1 resources=7 files=subnet-simple,subnet-simple-2,subnet-detailed,subnet-proxy,subnet-psc inventory=factory.yaml
# tftest modules=1 resources=9 files=subnet-simple,subnet-simple-2,subnet-detailed,subnet-proxy,subnet-psc inventory=factory.yaml
```

```yaml
Expand All @@ -338,13 +350,17 @@ region: europe-west1
description: Sample description
ip_cidr_range: 10.0.0.0/24
# optional attributes
enable_private_access: false # defaults to true
iam_users: ["[email protected]"] # grant compute/networkUser to users
iam_groups: ["[email protected]"] # grant compute/networkUser to groups
iam_service_accounts: ["[email protected]"]
secondary_ip_ranges: # map of secondary ip ranges
enable_private_access: false # defaults to true
iam: # grant roles/compute.networkUser
- group:[email protected]
- serviceAccount:[email protected]
- user:[email protected]
iam_additive: # grant roles/compute.networkUser
- user:[email protected]
- serviceAccount:[email protected]
secondary_ip_ranges: # map of secondary ip ranges
secondary-range-a: 192.168.0.0/24
flow_logs: # enable, set to empty map to use defaults
flow_logs: # enable, set to empty map to use defaults
aggregation_interval: "INTERVAL_5_SEC"
flow_sampling: 0.5
metadata: "INCLUDE_ALL_METADATA"
Expand Down Expand Up @@ -402,6 +418,7 @@ module "vpc" {
}
# tftest modules=5 resources=15 inventory=routes.yaml
```
<!-- BEGIN TFDOC -->

## Variables

Expand All @@ -422,10 +439,11 @@ module "vpc" {
| [shared_vpc_host](variables.tf#L121) | Enable shared VPC for this project. | <code>bool</code> | | <code>false</code> |
| [shared_vpc_service_projects](variables.tf#L127) | Shared VPC service projects to register with this host. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [subnet_iam](variables.tf#L133) | Subnet IAM bindings in {REGION/NAME => {ROLE => [MEMBERS]} format. | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [subnets](variables.tf#L139) | Subnet configuration. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10; enable_private_access &#61; optional&#40;bool, true&#41;&#10; flow_logs_config &#61; optional&#40;object&#40;&#123;&#10; aggregation_interval &#61; optional&#40;string&#41;&#10; filter_expression &#61; optional&#40;string&#41;&#10; flow_sampling &#61; optional&#40;number&#41;&#10; metadata &#61; optional&#40;string&#41;&#10; metadata_fields &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; ipv6 &#61; optional&#40;object&#40;&#123;&#10; access_type &#61; optional&#40;string&#41;&#10; enable_private_access &#61; optional&#40;bool, true&#41;&#10; &#125;&#41;&#41;&#10; secondary_ip_ranges &#61; optional&#40;map&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_proxy_only](variables.tf#L164) | List of proxy-only subnets for Regional HTTPS or Internal HTTPS load balancers. Note: Only one proxy-only subnet for each VPC network in each region can be active. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10; active &#61; bool&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_psc](variables.tf#L176) | List of subnets for Private Service Connect service producers. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [vpc_create](variables.tf#L187) | Create VPC. When set to false, uses a data source to reference existing VPC. | <code>bool</code> | | <code>true</code> |
| [subnet_iam_additive](variables.tf#L139) | Subnet IAM additive bindings in {REGION/NAME => {ROLE => [MEMBERS]}} format. | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [subnets](variables.tf#L146) | Subnet configuration. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10; enable_private_access &#61; optional&#40;bool, true&#41;&#10; flow_logs_config &#61; optional&#40;object&#40;&#123;&#10; aggregation_interval &#61; optional&#40;string&#41;&#10; filter_expression &#61; optional&#40;string&#41;&#10; flow_sampling &#61; optional&#40;number&#41;&#10; metadata &#61; optional&#40;string&#41;&#10; metadata_fields &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; ipv6 &#61; optional&#40;object&#40;&#123;&#10; access_type &#61; optional&#40;string&#41;&#10; enable_private_access &#61; optional&#40;bool, true&#41;&#10; &#125;&#41;&#41;&#10; secondary_ip_ranges &#61; optional&#40;map&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_proxy_only](variables.tf#L171) | List of proxy-only subnets for Regional HTTPS or Internal HTTPS load balancers. Note: Only one proxy-only subnet for each VPC network in each region can be active. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10; active &#61; bool&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [subnets_psc](variables.tf#L183) | List of subnets for Private Service Connect service producers. | <code title="list&#40;object&#40;&#123;&#10; name &#61; string&#10; ip_cidr_range &#61; string&#10; region &#61; string&#10; description &#61; optional&#40;string&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [vpc_create](variables.tf#L194) | Create VPC. When set to false, uses a data source to reference existing VPC. | <code>bool</code> | | <code>true</code> |

## Outputs

Expand All @@ -445,4 +463,3 @@ module "vpc" {
| [subnets_psc](outputs.tf#L112) | Private Service Connect subnet resources. | |

<!-- END TFDOC -->
The key format is `subnet_region/subnet_name`. For example `europe-west1/my_subnet`.
53 changes: 42 additions & 11 deletions modules/net-vpc/subnets.tf
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,39 @@ locals {
flow_logs_config = try(v.flow_logs, null)
ipv6 = try(v.ipv6, null)
secondary_ip_ranges = try(v.secondary_ip_ranges, null)
iam_groups = try(v.iam_groups, [])
iam_users = try(v.iam_users, [])
iam_service_accounts = try(v.iam_service_accounts, [])
iam = try(v.iam, [])
iam_additive = try(v.iam_additive, [])
purpose = try(v.purpose, null)
active = try(v.active, null)
}
}
_factory_subnets_iam_additive = flatten([
for k, v in local._factory_subnets : [
for member in lookup(v, "iam_additive", []) : {
member = member
subnet = k
role = "roles/compute.networkUser"
}
] if v.purpose == null
])
_factory_subnets_iam = [
for k, v in local._factory_subnets : {
subnet = k
role = "roles/compute.networkUser"
members = concat(
formatlist("group:%s", lookup(v, "iam_groups", [])),
formatlist("user:%s", lookup(v, "iam_users", [])),
formatlist("serviceAccount:%s", lookup(v, "iam_service_accounts", []))
)
} if v.purpose == null
subnet = k
role = "roles/compute.networkUser"
members = v.iam
} if v.purpose == null && v.iam != null
]
_subnet_iam_additive_members = flatten([
for subnet, roles in var.subnet_iam_additive : [
for role, members in roles : [
for member in members : {
member = member
role = role
subnet = subnet
}
]
]
])
_subnet_iam_members = flatten([
for subnet, roles in(var.subnet_iam == null ? {} : var.subnet_iam) : [
for role, members in roles : {
Expand All @@ -58,6 +73,10 @@ locals {
}
]
])
subnet_iam_additive_members = concat(
local._factory_subnets_iam_additive,
local._subnet_iam_additive_members
)
subnet_iam_members = concat(
[for k in local._factory_subnets_iam : k if length(k.members) > 0],
local._subnet_iam_members
Expand Down Expand Up @@ -151,3 +170,15 @@ resource "google_compute_subnetwork_iam_binding" "binding" {
role = each.value.role
members = each.value.members
}

resource "google_compute_subnetwork_iam_member" "binding" {
for_each = {
for binding in local.subnet_iam_additive_members :
"${binding.subnet}.${binding.role}.${binding.member}" => binding
}
project = var.project_id
subnetwork = google_compute_subnetwork.subnetwork[each.value.subnet].name
region = google_compute_subnetwork.subnetwork[each.value.subnet].region
role = each.value.role
member = each.value.member
}
7 changes: 7 additions & 0 deletions modules/net-vpc/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,13 @@ variable "subnet_iam" {
default = {}
}

variable "subnet_iam_additive" {
description = "Subnet IAM additive bindings in {REGION/NAME => {ROLE => [MEMBERS]}} format."
type = map(map(list(string)))
default = {}
nullable = false
}

variable "subnets" {
description = "Subnet configuration."
type = list(object({
Expand Down
18 changes: 11 additions & 7 deletions tests/modules/net_vpc/examples/subnet-iam.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,16 @@ values:
region: europe-west1
role: roles/compute.networkUser
subnetwork: subnet-1
module.vpc.google_compute_subnetwork_iam_binding.binding["europe-west1/subnet-2.roles/compute.networkUser"]:
module.vpc.google_compute_subnetwork_iam_member.binding["europe-west1/subnet-2.roles/compute.networkUser.user:[email protected]"]:
condition: []
members:
- group:[email protected]
- user:[email protected]
member: user:[email protected]
project: my-project
region: europe-west1
role: roles/compute.networkUser
subnetwork: subnet-2
module.vpc.google_compute_subnetwork_iam_member.binding["europe-west1/subnet-2.roles/compute.networkUser.group:[email protected]"]:
condition: []
member: group:[email protected]
project: my-project
region: europe-west1
role: roles/compute.networkUser
Expand All @@ -47,8 +52,7 @@ values:
counts:
google_compute_network: 1
google_compute_subnetwork: 2
google_compute_subnetwork_iam_binding: 2
modules: 1
resources: 5
google_compute_subnetwork_iam_binding: 1
google_compute_subnetwork_iam_member: 2

outputs: {}

0 comments on commit b44b2eb

Please sign in to comment.