Add support for `iam_additive` and simplify factory interface in net VPC module (#1259)
* initial implementation, no tests * change interface, align tests * add examples ToC * fix variable type, test module-level variable
This commit is contained in:
parent
50adf1da2a
commit
8a8b7ea35f
|
@ -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
|
## 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
|
### Simple VPC
|
||||||
|
|
||||||
|
@ -105,6 +115,8 @@ module "vpc" {
|
||||||
"user:user1@example.com", "group:group1@example.com"
|
"user:user1@example.com", "group:group1@example.com"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
subnet_iam_additive = {
|
||||||
"europe-west1/subnet-2" = {
|
"europe-west1/subnet-2" = {
|
||||||
"roles/compute.networkUser" = [
|
"roles/compute.networkUser" = [
|
||||||
"user:user2@example.com", "group:group2@example.com"
|
"user:user2@example.com", "group:group2@example.com"
|
||||||
|
@ -112,7 +124,7 @@ module "vpc" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# tftest modules=1 resources=5 inventory=subnet-iam.yaml
|
# tftest modules=1 resources=6 inventory=subnet-iam.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
### Peering
|
### Peering
|
||||||
|
@ -315,7 +327,7 @@ module "vpc" {
|
||||||
name = "my-network"
|
name = "my-network"
|
||||||
data_folder = "config/subnets"
|
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
|
```yaml
|
||||||
|
@ -338,13 +350,17 @@ region: europe-west1
|
||||||
description: Sample description
|
description: Sample description
|
||||||
ip_cidr_range: 10.0.0.0/24
|
ip_cidr_range: 10.0.0.0/24
|
||||||
# optional attributes
|
# optional attributes
|
||||||
enable_private_access: false # defaults to true
|
enable_private_access: false # defaults to true
|
||||||
iam_users: ["foobar@example.com"] # grant compute/networkUser to users
|
iam: # grant roles/compute.networkUser
|
||||||
iam_groups: ["lorem@example.com"] # grant compute/networkUser to groups
|
- group:lorem@example.com
|
||||||
iam_service_accounts: ["fbz@prj.iam.gserviceaccount.com"]
|
- serviceAccount:fbz@prj.iam.gserviceaccount.com
|
||||||
secondary_ip_ranges: # map of secondary ip ranges
|
- user:foobar@example.com
|
||||||
|
iam_additive: # grant roles/compute.networkUser
|
||||||
|
- user:foo@example.com
|
||||||
|
- serviceAccount:fbx@prj.iam.gserviceaccount.com
|
||||||
|
secondary_ip_ranges: # map of secondary ip ranges
|
||||||
secondary-range-a: 192.168.0.0/24
|
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"
|
aggregation_interval: "INTERVAL_5_SEC"
|
||||||
flow_sampling: 0.5
|
flow_sampling: 0.5
|
||||||
metadata: "INCLUDE_ALL_METADATA"
|
metadata: "INCLUDE_ALL_METADATA"
|
||||||
|
@ -402,6 +418,7 @@ module "vpc" {
|
||||||
}
|
}
|
||||||
# tftest modules=5 resources=15 inventory=routes.yaml
|
# tftest modules=5 resources=15 inventory=routes.yaml
|
||||||
```
|
```
|
||||||
|
<!-- BEGIN TFDOC -->
|
||||||
|
|
||||||
## Variables
|
## Variables
|
||||||
|
|
||||||
|
@ -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_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(string)</code> | | <code>[]</code> |
|
| [shared_vpc_service_projects](variables.tf#L127) | Shared VPC service projects to register with this host. | <code>list(string)</code> | | <code>[]</code> |
|
||||||
| [subnet_iam](variables.tf#L133) | Subnet IAM bindings in {REGION/NAME => {ROLE => [MEMBERS]} format. | <code>map(map(list(string)))</code> | | <code>{}</code> |
|
| [subnet_iam](variables.tf#L133) | Subnet IAM bindings in {REGION/NAME => {ROLE => [MEMBERS]} format. | <code>map(map(list(string)))</code> | | <code>{}</code> |
|
||||||
| [subnets](variables.tf#L139) | Subnet configuration. | <code title="list(object({ name = string ip_cidr_range = string region = string description = optional(string) enable_private_access = optional(bool, true) flow_logs_config = optional(object({ aggregation_interval = optional(string) filter_expression = optional(string) flow_sampling = optional(number) metadata = optional(string) metadata_fields = optional(list(string)) })) ipv6 = optional(object({ access_type = optional(string) enable_private_access = optional(bool, true) })) secondary_ip_ranges = optional(map(string)) }))">list(object({…}))</code> | | <code>[]</code> |
|
| [subnet_iam_additive](variables.tf#L139) | Subnet IAM additive bindings in {REGION/NAME => {ROLE => [MEMBERS]}} format. | <code>map(map(list(string)))</code> | | <code>{}</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(object({ name = string ip_cidr_range = string region = string description = optional(string) active = bool }))">list(object({…}))</code> | | <code>[]</code> |
|
| [subnets](variables.tf#L146) | Subnet configuration. | <code title="list(object({ name = string ip_cidr_range = string region = string description = optional(string) enable_private_access = optional(bool, true) flow_logs_config = optional(object({ aggregation_interval = optional(string) filter_expression = optional(string) flow_sampling = optional(number) metadata = optional(string) metadata_fields = optional(list(string)) })) ipv6 = optional(object({ access_type = optional(string) enable_private_access = optional(bool, true) })) secondary_ip_ranges = optional(map(string)) }))">list(object({…}))</code> | | <code>[]</code> |
|
||||||
| [subnets_psc](variables.tf#L176) | List of subnets for Private Service Connect service producers. | <code title="list(object({ name = string ip_cidr_range = string region = string description = optional(string) }))">list(object({…}))</code> | | <code>[]</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(object({ name = string ip_cidr_range = string region = string description = optional(string) active = bool }))">list(object({…}))</code> | | <code>[]</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> |
|
| [subnets_psc](variables.tf#L183) | List of subnets for Private Service Connect service producers. | <code title="list(object({ name = string ip_cidr_range = string region = string description = optional(string) }))">list(object({…}))</code> | | <code>[]</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
|
## Outputs
|
||||||
|
|
||||||
|
@ -445,4 +463,3 @@ module "vpc" {
|
||||||
| [subnets_psc](outputs.tf#L112) | Private Service Connect subnet resources. | |
|
| [subnets_psc](outputs.tf#L112) | Private Service Connect subnet resources. | |
|
||||||
|
|
||||||
<!-- END TFDOC -->
|
<!-- END TFDOC -->
|
||||||
The key format is `subnet_region/subnet_name`. For example `europe-west1/my_subnet`.
|
|
||||||
|
|
|
@ -31,24 +31,39 @@ locals {
|
||||||
flow_logs_config = try(v.flow_logs, null)
|
flow_logs_config = try(v.flow_logs, null)
|
||||||
ipv6 = try(v.ipv6, null)
|
ipv6 = try(v.ipv6, null)
|
||||||
secondary_ip_ranges = try(v.secondary_ip_ranges, null)
|
secondary_ip_ranges = try(v.secondary_ip_ranges, null)
|
||||||
iam_groups = try(v.iam_groups, [])
|
iam = try(v.iam, [])
|
||||||
iam_users = try(v.iam_users, [])
|
iam_additive = try(v.iam_additive, [])
|
||||||
iam_service_accounts = try(v.iam_service_accounts, [])
|
|
||||||
purpose = try(v.purpose, null)
|
purpose = try(v.purpose, null)
|
||||||
active = try(v.active, 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 = [
|
_factory_subnets_iam = [
|
||||||
for k, v in local._factory_subnets : {
|
for k, v in local._factory_subnets : {
|
||||||
subnet = k
|
subnet = k
|
||||||
role = "roles/compute.networkUser"
|
role = "roles/compute.networkUser"
|
||||||
members = concat(
|
members = v.iam
|
||||||
formatlist("group:%s", lookup(v, "iam_groups", [])),
|
} if v.purpose == null && v.iam != null
|
||||||
formatlist("user:%s", lookup(v, "iam_users", [])),
|
|
||||||
formatlist("serviceAccount:%s", lookup(v, "iam_service_accounts", []))
|
|
||||||
)
|
|
||||||
} if v.purpose == 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([
|
_subnet_iam_members = flatten([
|
||||||
for subnet, roles in(var.subnet_iam == null ? {} : var.subnet_iam) : [
|
for subnet, roles in(var.subnet_iam == null ? {} : var.subnet_iam) : [
|
||||||
for role, members in roles : {
|
for role, members in roles : {
|
||||||
|
@ -58,6 +73,10 @@ locals {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
|
subnet_iam_additive_members = concat(
|
||||||
|
local._factory_subnets_iam_additive,
|
||||||
|
local._subnet_iam_additive_members
|
||||||
|
)
|
||||||
subnet_iam_members = concat(
|
subnet_iam_members = concat(
|
||||||
[for k in local._factory_subnets_iam : k if length(k.members) > 0],
|
[for k in local._factory_subnets_iam : k if length(k.members) > 0],
|
||||||
local._subnet_iam_members
|
local._subnet_iam_members
|
||||||
|
@ -151,3 +170,15 @@ resource "google_compute_subnetwork_iam_binding" "binding" {
|
||||||
role = each.value.role
|
role = each.value.role
|
||||||
members = each.value.members
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -136,6 +136,13 @@ variable "subnet_iam" {
|
||||||
default = {}
|
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" {
|
variable "subnets" {
|
||||||
description = "Subnet configuration."
|
description = "Subnet configuration."
|
||||||
type = list(object({
|
type = list(object({
|
||||||
|
|
|
@ -34,11 +34,16 @@ values:
|
||||||
region: europe-west1
|
region: europe-west1
|
||||||
role: roles/compute.networkUser
|
role: roles/compute.networkUser
|
||||||
subnetwork: subnet-1
|
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:user2@example.com"]:
|
||||||
condition: []
|
condition: []
|
||||||
members:
|
member: user:user2@example.com
|
||||||
- group:group2@example.com
|
project: my-project
|
||||||
- user:user2@example.com
|
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:group2@example.com"]:
|
||||||
|
condition: []
|
||||||
|
member: group:group2@example.com
|
||||||
project: my-project
|
project: my-project
|
||||||
region: europe-west1
|
region: europe-west1
|
||||||
role: roles/compute.networkUser
|
role: roles/compute.networkUser
|
||||||
|
@ -47,8 +52,7 @@ values:
|
||||||
counts:
|
counts:
|
||||||
google_compute_network: 1
|
google_compute_network: 1
|
||||||
google_compute_subnetwork: 2
|
google_compute_subnetwork: 2
|
||||||
google_compute_subnetwork_iam_binding: 2
|
google_compute_subnetwork_iam_binding: 1
|
||||||
modules: 1
|
google_compute_subnetwork_iam_member: 2
|
||||||
resources: 5
|
|
||||||
|
|
||||||
outputs: {}
|
outputs: {}
|
||||||
|
|
Loading…
Reference in New Issue