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 support for iam_additive and simplify factory interface in net VPC module #1259

Merged
merged 5 commits into from
Mar 17, 2023
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
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: {}