diff --git a/modules/vpc-sc/README.md b/modules/vpc-sc/README.md
index 91d90d46..ee0d63a3 100644
--- a/modules/vpc-sc/README.md
+++ b/modules/vpc-sc/README.md
@@ -34,6 +34,8 @@ module "test" {
# tftest modules=1 resources=1 inventory=access-policy.yaml
```
+#### Scoped policy
+
If you need the module to create a scoped policy for you, specify 'scopes' of the policy in the `access_policy_create` variable:
```hcl
@@ -49,6 +51,23 @@ module "test" {
# tftest modules=1 resources=1 inventory=scoped-access-policy.yaml
```
+#### Access policy IAM
+
+The usual IAM interface is also implemented here, and can be used with service accounts or user principals:
+
+```hcl
+module "test" {
+ source = "./fabric/modules/vpc-sc"
+ access_policy = "12345678"
+ iam = {
+ "roles/accesscontextmanager.policyAdmin" = [
+ "user:foo@example.org"
+ ]
+ }
+}
+# tftest modules=1 resources=1
+```
+
### Access levels
As highlighted above, the `access_levels` type replicates the underlying resource structure.
@@ -190,6 +209,7 @@ module "test" {
| name | description | resources |
|---|---|---|
| [access-levels.tf](./access-levels.tf) | Access level resources. | google_access_context_manager_access_level
|
+| [iam.tf](./iam.tf) | IAM bindings | google_access_context_manager_access_policy_iam_binding
ยท google_access_context_manager_access_policy_iam_member
|
| [main.tf](./main.tf) | Module-level locals and resources. | google_access_context_manager_access_policy
|
| [outputs.tf](./outputs.tf) | Module outputs. | |
| [service-perimeters-bridge.tf](./service-perimeters-bridge.tf) | Bridge service perimeter resources. | google_access_context_manager_service_perimeter
|
@@ -205,9 +225,12 @@ module "test" {
| [access_levels](variables.tf#L17) | Access level definitions. | map(object({…}))
| | {}
|
| [access_policy_create](variables.tf#L61) | Access Policy configuration, fill in to create. Parent is in 'organizations/123456' format, scopes are in 'folders/456789' or 'projects/project_id' format. | object({…})
| | null
|
| [egress_policies](variables.tf#L71) | Egress policy definitions that can be referenced in perimeters. | map(object({…}))
| | {}
|
-| [ingress_policies](variables.tf#L102) | Ingress policy definitions that can be referenced in perimeters. | map(object({…}))
| | {}
|
-| [service_perimeters_bridge](variables.tf#L134) | Bridge service perimeters. | map(object({…}))
| | {}
|
-| [service_perimeters_regular](variables.tf#L144) | Regular service perimeters. | map(object({…}))
| | {}
|
+| [iam](variables.tf#L102) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string))
| | {}
|
+| [iam_bindings](variables.tf#L108) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [iam_bindings_additive](variables.tf#L123) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…}))
| | {}
|
+| [ingress_policies](variables.tf#L138) | Ingress policy definitions that can be referenced in perimeters. | map(object({…}))
| | {}
|
+| [service_perimeters_bridge](variables.tf#L170) | Bridge service perimeters. | map(object({…}))
| | {}
|
+| [service_perimeters_regular](variables.tf#L180) | Regular service perimeters. | map(object({…}))
| | {}
|
## Outputs
diff --git a/modules/vpc-sc/iam.tf b/modules/vpc-sc/iam.tf
new file mode 100644
index 00000000..9b475b68
--- /dev/null
+++ b/modules/vpc-sc/iam.tf
@@ -0,0 +1,54 @@
+/**
+ * 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.
+ */
+
+# tfdoc:file:description IAM bindings
+
+resource "google_access_context_manager_access_policy_iam_binding" "authoritative" {
+ for_each = var.iam
+ name = local.access_policy
+ role = each.key
+ members = each.value
+}
+
+resource "google_access_context_manager_access_policy_iam_binding" "bindings" {
+ for_each = var.iam_bindings
+ name = local.access_policy
+ role = each.value.role
+ members = each.value.members
+ dynamic "condition" {
+ for_each = each.value.condition == null ? [] : [""]
+ content {
+ expression = each.value.condition.expression
+ title = each.value.condition.title
+ description = each.value.condition.description
+ }
+ }
+}
+
+resource "google_access_context_manager_access_policy_iam_member" "bindings" {
+ for_each = var.iam_bindings_additive
+ name = local.access_policy
+ role = each.value.role
+ member = each.value.member
+ dynamic "condition" {
+ for_each = each.value.condition == null ? [] : [""]
+ content {
+ expression = each.value.condition.expression
+ title = each.value.condition.title
+ description = each.value.condition.description
+ }
+ }
+}
diff --git a/modules/vpc-sc/variables.tf b/modules/vpc-sc/variables.tf
index 8ce4b41e..008d7ae2 100644
--- a/modules/vpc-sc/variables.tf
+++ b/modules/vpc-sc/variables.tf
@@ -99,6 +99,42 @@ variable "egress_policies" {
}
}
+variable "iam" {
+ description = "IAM bindings in {ROLE => [MEMBERS]} format."
+ type = map(list(string))
+ default = {}
+}
+
+variable "iam_bindings" {
+ description = "Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary."
+ type = map(object({
+ members = list(string)
+ role = string
+ condition = optional(object({
+ expression = string
+ title = string
+ description = optional(string)
+ }))
+ }))
+ nullable = false
+ default = {}
+}
+
+variable "iam_bindings_additive" {
+ description = "Individual additive IAM bindings. Keys are arbitrary."
+ type = map(object({
+ member = string
+ role = string
+ condition = optional(object({
+ expression = string
+ title = string
+ description = optional(string)
+ }))
+ }))
+ nullable = false
+ default = {}
+}
+
variable "ingress_policies" {
description = "Ingress policy definitions that can be referenced in perimeters."
type = map(object({