diff --git a/modules/apigee/README.md b/modules/apigee/README.md
index 7692d6f4b0..5a05ecb353 100644
--- a/modules/apigee/README.md
+++ b/modules/apigee/README.md
@@ -17,6 +17,7 @@ This module simplifies the creation of a Apigee resources (organization, environ
- [New instance (Non VPC Peering Provisioning Mode)](#new-instance-non-vpc-peering-provisioning-mode)
- [New endpoint attachment](#new-endpoint-attachment)
- [Apigee add-ons](#apigee-add-ons)
+ - [IAM](#iam)
- [Variables](#variables)
- [Outputs](#outputs)
@@ -87,7 +88,6 @@ module "apigee" {
When a new Apigee organization is created, it is automatically peered to the authorized network. You can prevent this from happening by using the `disable_vpc_peering` key in the `organization` variable, as shown below:
-
```hcl
module "apigee" {
source = "./fabric/modules/apigee"
@@ -117,7 +117,6 @@ module "apigee" {
# tftest modules=1 resources=6 inventory=no-peering.yaml
```
-
### All resources (CLOUD)
```hcl
@@ -147,9 +146,6 @@ module "apigee" {
display_name = "APIs prod"
description = "APIs prod"
envgroups = ["prod"]
- iam = {
- "roles/viewer" = ["group:devops@myorg.com"]
- }
}
}
instances = {
@@ -176,7 +172,7 @@ module "apigee" {
}
}
}
-# tftest modules=1 resources=15
+# tftest modules=1 resources=14
```
### All resources (HYBRID control plane)
@@ -205,13 +201,10 @@ module "apigee" {
display_name = "APIs prod"
description = "APIs prod"
envgroups = ["prod"]
- iam = {
- "roles/viewer" = ["group:devops@myorg.com"]
- }
}
}
}
-# tftest modules=1 resources=8
+# tftest modules=1 resources=7
```
### New environment group
@@ -311,18 +304,69 @@ module "apigee" {
}
# tftest modules=1 resources=1
```
+
+### IAM
+
+```hcl
+module "apigee" {
+ source = "./fabric/modules/apigee"
+ project_id = "my-project"
+ organization = {
+ display_name = "My Organization"
+ description = "My Organization"
+ authorized_network = "my-vpc"
+ runtime_type = "CLOUD"
+ billing_type = "PAYG"
+ database_encryption_key = "123456789"
+ analytics_region = "europe-west1"
+ }
+ envgroups = {
+ test = ["test.example.com"]
+ prod = ["prod.example.com"]
+ }
+ environments = {
+ apis-test = {
+ display_name = "APIs test"
+ description = "APIs Test"
+ envgroups = ["test"]
+ iam = {
+ "roles/apigee.environmentAdmin" = ["group:apigee-env-admin@myorg.com"]
+ }
+ iam_bindings_additive = {
+ viewer = {
+ role = "roles/viewer"
+ member = "user:user1@myorg.com"
+ }
+ }
+ }
+ apis-prod = {
+ display_name = "APIs prod"
+ description = "APIs prod"
+ envgroups = ["prod"]
+ iam_bindings = {
+ apigee-env-admin = {
+ role = "roles/apigee.environmentAdmin"
+ members = ["group:apigee-env-admin@myorg.com"]
+ }
+ }
+ }
+ }
+}
+# tftest modules=1 resources=10
+```
+
## Variables
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [project_id](variables.tf#L117) | Project ID. | string
| ✓ | |
+| [project_id](variables.tf#L125) | Project ID. | string
| ✓ | |
| [addons_config](variables.tf#L17) | Addons configuration. | object({…})
| | null
|
| [endpoint_attachments](variables.tf#L29) | Endpoint attachments. | map(object({…}))
| | {}
|
| [envgroups](variables.tf#L39) | Environment groups (NAME => [HOSTNAMES]). | map(list(string))
| | {}
|
-| [environments](variables.tf#L46) | Environments. | map(object({…}))
| | {}
|
-| [instances](variables.tf#L64) | Instances ([REGION] => [INSTANCE]). | map(object({…}))
| | {}
|
-| [organization](variables.tf#L89) | Apigee organization. If set to null the organization must already exist. | object({…})
| | null
|
+| [environments](variables.tf#L46) | Environments. | map(object({…}))
| | {}
|
+| [instances](variables.tf#L72) | Instances ([REGION] => [INSTANCE]). | map(object({…}))
| | {}
|
+| [organization](variables.tf#L97) | Apigee organization. If set to null the organization must already exist. | object({…})
| | null
|
## Outputs
diff --git a/modules/apigee/iam.tf b/modules/apigee/iam.tf
new file mode 100644
index 0000000000..fc6d96f206
--- /dev/null
+++ b/modules/apigee/iam.tf
@@ -0,0 +1,57 @@
+/**
+ * Copyright 2023 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.
+ */
+
+resource "google_apigee_environment_iam_binding" "authoritative" {
+ for_each = merge(concat([for k1, v1 in var.environments : {
+ for k2, v2 in v1.iam : "${k1}-${k2}" => {
+ environment = "${k1}"
+ role = k2
+ members = v2
+ }
+ }])...)
+ org_id = local.org_id
+ env_id = google_apigee_environment.environments[each.value.environment].name
+ role = each.value.role
+ members = each.value.members
+}
+
+resource "google_apigee_environment_iam_binding" "bindings" {
+ for_each = merge(concat([for k1, v1 in var.environments : {
+ for k2, v2 in coalesce(v1.iam_bindings, {}) : "${k1}-${k2}" => {
+ environment = "${k1}"
+ role = v2.role
+ members = v2.members
+ }
+ }])...)
+ org_id = local.org_id
+ env_id = google_apigee_environment.environments[each.value.environment].name
+ role = each.value.role
+ members = each.value.members
+}
+
+resource "google_apigee_environment_iam_member" "bindings" {
+ for_each = merge(concat([for k1, v1 in var.environments : {
+ for k2, v2 in coalesce(v1.iam_bindings_additive, {}) : "${k1}-${k2}" => {
+ environment = "${k1}"
+ role = v2.role
+ member = v2.member
+ }
+ }])...)
+ org_id = local.org_id
+ env_id = google_apigee_environment.environments[each.value.environment].name
+ role = each.value.role
+ member = each.value.member
+}
diff --git a/modules/apigee/main.tf b/modules/apigee/main.tf
index 46f7655564..be571a8ae2 100644
--- a/modules/apigee/main.tf
+++ b/modules/apigee/main.tf
@@ -62,7 +62,7 @@ resource "google_apigee_environment" "environments" {
resource "google_apigee_envgroup_attachment" "envgroup_attachments" {
for_each = merge(concat([for k1, v1 in var.environments : {
- for v2 in coalesce(v1.envgroups, []) : "${k1}-${v2}" => {
+ for v2 in v1.envgroups : "${k1}-${v2}" => {
environment = k1
envgroup = v2
}
@@ -72,20 +72,6 @@ resource "google_apigee_envgroup_attachment" "envgroup_attachments" {
depends_on = [google_apigee_envgroup.envgroups]
}
-resource "google_apigee_environment_iam_binding" "binding" {
- for_each = merge(concat([for k1, v1 in var.environments : {
- for k2, v2 in coalesce(v1.iam, {}) : "${k1}-${k2}" => {
- environment = "${k1}"
- role = k2
- members = v2
- }
- }])...)
- org_id = local.org_id
- env_id = google_apigee_environment.environments[each.value.environment].name
- role = each.value.role
- members = each.value.members
-}
-
resource "google_apigee_instance" "instances" {
for_each = var.instances
name = coalesce(each.value.name, "instance-${each.key}")
@@ -114,7 +100,7 @@ resource "google_apigee_nat_address" "apigee_nat" {
resource "google_apigee_instance_attachment" "instance_attachments" {
for_each = merge(concat([for k1, v1 in var.instances : {
- for v2 in coalesce(v1.environments, []) :
+ for v2 in v1.environments :
"${k1}-${v2}" => {
instance = k1
environment = v2
diff --git a/modules/apigee/variables.tf b/modules/apigee/variables.tf
index 78549507e5..7ec2cc2d64 100644
--- a/modules/apigee/variables.tf
+++ b/modules/apigee/variables.tf
@@ -54,8 +54,16 @@ variable "environments" {
min_node_count = optional(number)
max_node_count = optional(number)
}))
- iam = optional(map(list(string)))
- envgroups = optional(list(string))
+ iam = optional(map(list(string)), {})
+ iam_bindings = optional(map(object({
+ role = string
+ members = list(string)
+ })), {})
+ iam_bindings_additive = optional(map(object({
+ role = string
+ member = string
+ })), {})
+ envgroups = optional(list(string), [])
}))
default = {}
nullable = false
@@ -72,7 +80,7 @@ variable "instances" {
disk_encryption_key = optional(string)
consumer_accept_list = optional(list(string))
enable_nat = optional(bool, false)
- environments = optional(list(string))
+ environments = optional(list(string), [])
}))
validation {
condition = alltrue([
diff --git a/tests/modules/apigee/all_psc_mode.yaml b/tests/modules/apigee/all_psc_mode.yaml
index c31c713ae7..e702821385 100644
--- a/tests/modules/apigee/all_psc_mode.yaml
+++ b/tests/modules/apigee/all_psc_mode.yaml
@@ -41,7 +41,7 @@ values:
description: APIs Test
display_name: APIs test
name: apis-test
- google_apigee_environment_iam_binding.binding["apis-prod-roles/viewer"]:
+ google_apigee_environment_iam_binding.authoritative["apis-prod-roles/viewer"]:
condition: []
env_id: apis-prod
members:
diff --git a/tests/modules/apigee/all_vpc_mode.yaml b/tests/modules/apigee/all_vpc_mode.yaml
index 2d39429c75..b5ebdec1bc 100644
--- a/tests/modules/apigee/all_vpc_mode.yaml
+++ b/tests/modules/apigee/all_vpc_mode.yaml
@@ -42,7 +42,7 @@ values:
description: APIs Test
display_name: APIs test
name: apis-test
- google_apigee_environment_iam_binding.binding["apis-prod-roles/viewer"]:
+ google_apigee_environment_iam_binding.authoritative["apis-prod-roles/viewer"]:
condition: []
env_id: apis-prod
members: