diff --git a/modules/compute-vm/README.md b/modules/compute-vm/README.md index ee25ac10f..2f715555a 100644 --- a/modules/compute-vm/README.md +++ b/modules/compute-vm/README.md @@ -278,34 +278,34 @@ module "instance-group" { | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [name](variables.tf#L180) | Instance name. | string | ✓ | | -| [network_interfaces](variables.tf#L185) | Network interfaces configuration. Use self links for Shared VPC, set addresses to null if not needed. | list(object({…})) | ✓ | | -| [project_id](variables.tf#L222) | Project id. | string | ✓ | | -| [zone](variables.tf#L281) | Compute zone. | string | ✓ | | +| [name](variables.tf#L181) | Instance name. | string | ✓ | | +| [network_interfaces](variables.tf#L186) | Network interfaces configuration. Use self links for Shared VPC, set addresses to null if not needed. | list(object({…})) | ✓ | | +| [project_id](variables.tf#L223) | Project id. | string | ✓ | | +| [zone](variables.tf#L282) | Compute zone. | string | ✓ | | | [attached_disk_defaults](variables.tf#L17) | Defaults for attached disks options. | object({…}) | | {…} | -| [attached_disks](variables.tf#L38) | Additional disks, if options is null defaults will be used in its place. Source type is one of 'image' (zonal disks in vms and template), 'snapshot' (vm), 'existing', and null. | list(object({…})) | | [] | -| [boot_disk](variables.tf#L81) | Boot disk properties. | object({…}) | | {…} | -| [can_ip_forward](variables.tf#L97) | Enable IP forwarding. | bool | | false | -| [confidential_compute](variables.tf#L103) | Enable Confidential Compute for these instances. | bool | | false | -| [create_template](variables.tf#L109) | Create instance template instead of instances. | bool | | false | -| [description](variables.tf#L114) | Description of a Compute Instance. | string | | "Managed by the compute-vm Terraform module." | -| [enable_display](variables.tf#L120) | Enable virtual display on the instances. | bool | | false | -| [encryption](variables.tf#L126) | Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk. | object({…}) | | null | -| [group](variables.tf#L136) | Define this variable to create an instance group for instances. Disabled for template use. | object({…}) | | null | -| [hostname](variables.tf#L144) | Instance FQDN name. | string | | null | -| [iam](variables.tf#L150) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} | -| [instance_type](variables.tf#L156) | Instance type. | string | | "f1-micro" | -| [labels](variables.tf#L162) | Instance labels. | map(string) | | {} | -| [metadata](variables.tf#L168) | Instance metadata. | map(string) | | {} | -| [min_cpu_platform](variables.tf#L174) | Minimum CPU platform. | string | | null | -| [options](variables.tf#L200) | Instance options. | object({…}) | | {…} | -| [scratch_disks](variables.tf#L227) | Scratch disks configuration. | object({…}) | | {…} | -| [service_account](variables.tf#L239) | Service account email. Unused if service account is auto-created. | string | | null | -| [service_account_create](variables.tf#L245) | Auto-create service account. | bool | | false | -| [service_account_scopes](variables.tf#L253) | Scopes applied to service account. | list(string) | | [] | -| [shielded_config](variables.tf#L259) | Shielded VM configuration of the instances. | object({…}) | | null | -| [tag_bindings](variables.tf#L269) | Tag bindings for this instance, in key => tag value id format. | map(string) | | null | -| [tags](variables.tf#L275) | Instance network tags for firewall rule targets. | list(string) | | [] | +| [attached_disks](variables.tf#L38) | Additional disks, if options is null defaults will be used in its place. Source type is one of 'image' (zonal disks in vms and template), 'snapshot' (vm), 'existing', and null. | list(object({…})) | | [] | +| [boot_disk](variables.tf#L82) | Boot disk properties. | object({…}) | | {…} | +| [can_ip_forward](variables.tf#L98) | Enable IP forwarding. | bool | | false | +| [confidential_compute](variables.tf#L104) | Enable Confidential Compute for these instances. | bool | | false | +| [create_template](variables.tf#L110) | Create instance template instead of instances. | bool | | false | +| [description](variables.tf#L115) | Description of a Compute Instance. | string | | "Managed by the compute-vm Terraform module." | +| [enable_display](variables.tf#L121) | Enable virtual display on the instances. | bool | | false | +| [encryption](variables.tf#L127) | Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk. | object({…}) | | null | +| [group](variables.tf#L137) | Define this variable to create an instance group for instances. Disabled for template use. | object({…}) | | null | +| [hostname](variables.tf#L145) | Instance FQDN name. | string | | null | +| [iam](variables.tf#L151) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} | +| [instance_type](variables.tf#L157) | Instance type. | string | | "f1-micro" | +| [labels](variables.tf#L163) | Instance labels. | map(string) | | {} | +| [metadata](variables.tf#L169) | Instance metadata. | map(string) | | {} | +| [min_cpu_platform](variables.tf#L175) | Minimum CPU platform. | string | | null | +| [options](variables.tf#L201) | Instance options. | object({…}) | | {…} | +| [scratch_disks](variables.tf#L228) | Scratch disks configuration. | object({…}) | | {…} | +| [service_account](variables.tf#L240) | Service account email. Unused if service account is auto-created. | string | | null | +| [service_account_create](variables.tf#L246) | Auto-create service account. | bool | | false | +| [service_account_scopes](variables.tf#L254) | Scopes applied to service account. | list(string) | | [] | +| [shielded_config](variables.tf#L260) | Shielded VM configuration of the instances. | object({…}) | | null | +| [tag_bindings](variables.tf#L270) | Tag bindings for this instance, in key => tag value id format. | map(string) | | null | +| [tags](variables.tf#L276) | Instance network tags for firewall rule targets. | list(string) | | [] | ## Outputs diff --git a/modules/compute-vm/main.tf b/modules/compute-vm/main.tf index 32051555c..31e370672 100644 --- a/modules/compute-vm/main.tf +++ b/modules/compute-vm/main.tf @@ -17,7 +17,7 @@ locals { attached_disks = { for disk in var.attached_disks : - disk.name => merge(disk, { + (disk.name != null ? disk.name : disk.device_name) => merge(disk, { options = disk.options == null ? var.attached_disk_defaults : disk.options }) } @@ -138,7 +138,7 @@ resource "google_compute_instance" "default" { for_each = local.attached_disks_zonal iterator = config content { - device_name = config.value.name + device_name = config.value.device_name != null ? config.value.device_name : config.value.name mode = config.value.options.mode source = ( config.value.source_type == "attach" @@ -152,7 +152,7 @@ resource "google_compute_instance" "default" { for_each = local.attached_disks_regional iterator = config content { - device_name = config.value.name + device_name = config.value.device_name != null ? config.value.device_name : config.value.name mode = config.value.options.mode source = ( config.value.source_type == "attach" @@ -285,7 +285,7 @@ resource "google_compute_instance_template" "default" { iterator = config content { auto_delete = config.value.options.auto_delete - device_name = config.value.name + device_name = config.value.device_name != null ? config.value.device_name : config.value.name # Cannot use `source` with any of the fields in # [disk_size_gb disk_name disk_type source_image labels] disk_type = ( diff --git a/modules/compute-vm/variables.tf b/modules/compute-vm/variables.tf index 4287999fe..dc5651775 100644 --- a/modules/compute-vm/variables.tf +++ b/modules/compute-vm/variables.tf @@ -39,6 +39,7 @@ variable "attached_disks" { description = "Additional disks, if options is null defaults will be used in its place. Source type is one of 'image' (zonal disks in vms and template), 'snapshot' (vm), 'existing', and null." type = list(object({ name = string + device_name = optional(string) size = string source = optional(string) source_type = optional(string) diff --git a/modules/folder/README.md b/modules/folder/README.md index 6ed674f35..e1ad6809e 100644 --- a/modules/folder/README.md +++ b/modules/folder/README.md @@ -2,9 +2,7 @@ This module allows the creation and management of folders, including support for IAM bindings, organization policies, and hierarchical firewall rules. -## Examples - -### IAM bindings +## Basic example with IAM bindings ```hcl module "folder" { @@ -14,17 +12,26 @@ module "folder" { group_iam = { "cloud-owners@example.org" = [ "roles/owner", + "roles/resourcemanager.folderAdmin", "roles/resourcemanager.projectCreator" ] } iam = { - "roles/owner" = ["user:one@example.com"] + "roles/owner" = ["user:one@example.org"] + } + iam_additive = { + "roles/compute.admin" = ["user:a1@example.org", "user:a2@example.org"] + "roles/compute.viewer" = ["user:a2@example.org"] + } + iam_additive_members = { + "user:am1@example.org" = ["roles/storage.admin"] + "user:am2@example.org" = ["roles/storage.objectViewer"] } } -# tftest modules=1 resources=3 +# tftest modules=1 resources=9 inventory=iam.yaml ``` -### Organization policies +## Organization policies To manage organization policies, the `orgpolicy.googleapis.com` service should be enabled in the quota project. @@ -72,70 +79,14 @@ module "folder" { } } } -# tftest modules=1 resources=8 +# tftest modules=1 resources=8 inventory=org-policies.yaml ``` ### Organization policy factory See the [organization policy factory in the project module](../project#organization-policy-factory). -### Firewall policy factory - -In the same way as for the [organization](../organization) module, the in-built factory allows you to define a single policy, using one file for rules, and an optional file for CIDR range substitution variables. Remember that non-absolute paths are relative to the root module (the folder where you run `terraform`). - -```hcl -module "folder" { - source = "./fabric/modules/folder" - parent = "organizations/1234567890" - name = "Folder name" - firewall_policy_factory = { - cidr_file = "configs/firewall-policies/cidrs.yaml" - policy_name = null - rules_file = "configs/firewall-policies/rules.yaml" - } - firewall_policy_association = { - factory-policy = module.folder.firewall_policy_id["factory"] - } -} -# tftest modules=1 resources=5 files=cidrs,rules -``` - -```yaml -# tftest-file id=cidrs path=configs/firewall-policies/cidrs.yaml -rfc1918: - - 10.0.0.0/8 - - 172.16.0.0/12 - - 192.168.0.0/16 -``` - -```yaml -# tftest-file id=rules path=configs/firewall-policies/rules.yaml -allow-admins: - description: Access from the admin subnet to all subnets - direction: INGRESS - action: allow - priority: 1000 - ranges: - - $rfc1918 - ports: - all: [] - target_resources: null - enable_logging: false - -allow-ssh-from-iap: - description: Enable SSH from IAP - direction: INGRESS - action: allow - priority: 1002 - ranges: - - 35.235.240.0/20 - ports: - tcp: ["22"] - target_resources: null - enable_logging: false -``` - -### Logging Sinks +## Logging Sinks ```hcl module "gcs" { @@ -164,7 +115,6 @@ module "bucket" { id = "bucket" } - module "folder-sink" { source = "./fabric/modules/folder" parent = "folders/657104291943" @@ -198,10 +148,19 @@ module "folder-sink" { no-gce-instances = "resource.type=gce_instance" } } -# tftest modules=5 resources=14 +# tftest modules=5 resources=14 inventory=logging.yaml ``` -### Hierarchical firewall policies +## Hierarchical firewall policies + +Hierarchical firewall policies can be managed in two ways: + +- via the `firewall_policies` variable, to directly define policies and rules in Terraform +- via the `firewall_policy_factory` variable, to leverage external YaML files via a simple "factory" embedded in the module ([see here](../../blueprints/factories) for more context on factories) + +Once you have policies (either created via the module or externally), you can associate them using the `firewall_policy_association` variable. + +### Directly defined firewall policies ```hcl module "folder1" { @@ -211,6 +170,17 @@ module "folder1" { firewall_policies = { iap-policy = { + allow-admins = { + description = "Access from the admin subnet to all subnets" + direction = "INGRESS" + action = "allow" + priority = 1000 + ranges = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"] + ports = { all = [] } + target_service_accounts = null + target_resources = null + logging = false + } allow-iap-ssh = { description = "Always allow ssh from IAP" direction = "INGRESS" @@ -237,7 +207,71 @@ module "folder2" { iap-policy = module.folder1.firewall_policy_id["iap-policy"] } } -# tftest modules=2 resources=6 +# tftest modules=2 resources=7 inventory=hfw.yaml +``` +### Firewall policy factory + +The in-built factory allows you to define a single policy, using one file for rules, and an optional file for CIDR range substitution variables. Remember that non-absolute paths are relative to the root module (the folder where you run `terraform`). + +```hcl +module "folder1" { + source = "./fabric/modules/folder" + parent = var.organization_id + name = "policy-container" + firewall_policy_factory = { + cidr_file = "configs/firewall-policies/cidrs.yaml" + policy_name = "iap-policy" + rules_file = "configs/firewall-policies/rules.yaml" + } + firewall_policy_association = { + iap-policy = "iap-policy" + } +} + +module "folder2" { + source = "./fabric/modules/folder" + parent = var.organization_id + name = "hf2" + firewall_policy_association = { + iap-policy = module.folder1.firewall_policy_id["iap-policy"] + } +} +# tftest modules=2 resources=7 files=cidrs,rules inventory=hfw.yaml +``` + +```yaml +# tftest-file id=cidrs path=configs/firewall-policies/cidrs.yaml +rfc1918: + - 10.0.0.0/8 + - 172.16.0.0/12 + - 192.168.0.0/16 +``` + +```yaml +# tftest-file id=rules path=configs/firewall-policies/rules.yaml +allow-admins: + description: Access from the admin subnet to all subnets + direction: INGRESS + action: allow + priority: 1000 + ranges: + - $rfc1918 + ports: + all: [] + target_resources: null + logging: false + +allow-iap-ssh: + description: "Always allow ssh from IAP" + direction: INGRESS + action: allow + priority: 100 + ranges: + - 35.235.240.0/20 + ports: + tcp: ["22"] + target_resources: null + logging: false ``` ## Tags @@ -269,7 +303,7 @@ module "folder" { foo = "tagValues/12345678" } } -# tftest modules=2 resources=6 +# tftest modules=2 resources=6 inventory=tags.yaml ``` diff --git a/modules/folder/organization-policies.tf b/modules/folder/organization-policies.tf index 999d1c586..47532f21b 100644 --- a/modules/folder/organization-policies.tf +++ b/modules/folder/organization-policies.tf @@ -95,23 +95,6 @@ resource "google_org_policy_policy" "default" { inherit_from_parent = each.value.inherit_from_parent reset = each.value.reset - rules { - allow_all = try(each.value.allow.all, null) == true ? "TRUE" : null - deny_all = try(each.value.deny.all, null) == true ? "TRUE" : null - enforce = ( - each.value.is_boolean_policy && each.value.enforce != null - ? upper(tostring(each.value.enforce)) - : null - ) - dynamic "values" { - for_each = each.value.has_values ? [1] : [] - content { - allowed_values = try(each.value.allow.values, null) - denied_values = try(each.value.deny.values, null) - } - } - } - dynamic "rules" { for_each = each.value.rules iterator = rule @@ -138,5 +121,22 @@ resource "google_org_policy_policy" "default" { } } } + + rules { + allow_all = try(each.value.allow.all, null) == true ? "TRUE" : null + deny_all = try(each.value.deny.all, null) == true ? "TRUE" : null + enforce = ( + each.value.is_boolean_policy && each.value.enforce != null + ? upper(tostring(each.value.enforce)) + : null + ) + dynamic "values" { + for_each = each.value.has_values ? [1] : [] + content { + allowed_values = try(each.value.allow.values, null) + denied_values = try(each.value.deny.values, null) + } + } + } } } diff --git a/modules/organization/organization-policies.tf b/modules/organization/organization-policies.tf index 62d464557..1a99ef9a1 100644 --- a/modules/organization/organization-policies.tf +++ b/modules/organization/organization-policies.tf @@ -95,23 +95,6 @@ resource "google_org_policy_policy" "default" { inherit_from_parent = each.value.inherit_from_parent reset = each.value.reset - rules { - allow_all = try(each.value.allow.all, null) == true ? "TRUE" : null - deny_all = try(each.value.deny.all, null) == true ? "TRUE" : null - enforce = ( - each.value.is_boolean_policy && each.value.enforce != null - ? upper(tostring(each.value.enforce)) - : null - ) - dynamic "values" { - for_each = each.value.has_values ? [1] : [] - content { - allowed_values = try(each.value.allow.values, null) - denied_values = try(each.value.deny.values, null) - } - } - } - dynamic "rules" { for_each = each.value.rules iterator = rule @@ -138,6 +121,23 @@ resource "google_org_policy_policy" "default" { } } } + + rules { + allow_all = try(each.value.allow.all, null) == true ? "TRUE" : null + deny_all = try(each.value.deny.all, null) == true ? "TRUE" : null + enforce = ( + each.value.is_boolean_policy && each.value.enforce != null + ? upper(tostring(each.value.enforce)) + : null + ) + dynamic "values" { + for_each = each.value.has_values ? [1] : [] + content { + allowed_values = try(each.value.allow.values, null) + denied_values = try(each.value.deny.values, null) + } + } + } } depends_on = [ diff --git a/modules/project/organization-policies.tf b/modules/project/organization-policies.tf index 7763aff40..4ff5bb992 100644 --- a/modules/project/organization-policies.tf +++ b/modules/project/organization-policies.tf @@ -95,23 +95,6 @@ resource "google_org_policy_policy" "default" { inherit_from_parent = each.value.inherit_from_parent reset = each.value.reset - rules { - allow_all = try(each.value.allow.all, null) == true ? "TRUE" : null - deny_all = try(each.value.deny.all, null) == true ? "TRUE" : null - enforce = ( - each.value.is_boolean_policy && each.value.enforce != null - ? upper(tostring(each.value.enforce)) - : null - ) - dynamic "values" { - for_each = each.value.has_values ? [1] : [] - content { - allowed_values = try(each.value.allow.values, null) - denied_values = try(each.value.deny.values, null) - } - } - } - dynamic "rules" { for_each = each.value.rules iterator = rule @@ -138,5 +121,22 @@ resource "google_org_policy_policy" "default" { } } } + + rules { + allow_all = try(each.value.allow.all, null) == true ? "TRUE" : null + deny_all = try(each.value.deny.all, null) == true ? "TRUE" : null + enforce = ( + each.value.is_boolean_policy && each.value.enforce != null + ? upper(tostring(each.value.enforce)) + : null + ) + dynamic "values" { + for_each = each.value.has_values ? [1] : [] + content { + allowed_values = try(each.value.allow.values, null) + denied_values = try(each.value.deny.values, null) + } + } + } } } diff --git a/tests/examples/test_plan.py b/tests/examples/test_plan.py index cbcc0b16e..5f902cbe7 100644 --- a/tests/examples/test_plan.py +++ b/tests/examples/test_plan.py @@ -49,6 +49,11 @@ def test_example(plan_validator, tmp_path, example): summary = plan_validator(module_path=tmp_path, inventory_paths=inventory, tf_var_files=[]) + import yaml + print(yaml.dump({"values": summary.values})) + print(yaml.dump({"counts": summary.counts})) + print(yaml.dump({"outputs": summary.outputs})) + counts = summary.counts num_modules, num_resources = counts['modules'], counts['resources'] assert expected_modules == num_modules, 'wrong number of modules' diff --git a/tests/modules/folder/common.tfvars b/tests/modules/folder/common.tfvars new file mode 100644 index 000000000..aebc74a01 --- /dev/null +++ b/tests/modules/folder/common.tfvars @@ -0,0 +1,2 @@ +parent = "organizations/12345678" +name = "folder-a" diff --git a/tests/modules/folder/examples/hfw.yaml b/tests/modules/folder/examples/hfw.yaml new file mode 100644 index 000000000..57abe480e --- /dev/null +++ b/tests/modules/folder/examples/hfw.yaml @@ -0,0 +1,67 @@ +# Copyright 2022 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. + +values: + module.folder1.google_compute_firewall_policy.policy["iap-policy"]: + description: null + short_name: iap-policy + module.folder1.google_compute_firewall_policy_association.association["iap-policy"]: {} + module.folder1.google_compute_firewall_policy_rule.rule["iap-policy-allow-admins"]: + action: allow + description: Access from the admin subnet to all subnets + direction: INGRESS + disabled: null + enable_logging: false + match: + - dest_ip_ranges: null + layer4_configs: + - ip_protocol: all + ports: [] + src_ip_ranges: + - 10.0.0.0/8 + - 172.16.0.0/12 + - 192.168.0.0/16 + priority: 1000 + target_resources: null + target_service_accounts: null + module.folder1.google_compute_firewall_policy_rule.rule["iap-policy-allow-iap-ssh"]: + action: allow + description: Always allow ssh from IAP + direction: INGRESS + disabled: null + enable_logging: false + match: + - dest_ip_ranges: null + layer4_configs: + - ip_protocol: tcp + ports: + - '22' + src_ip_ranges: + - 35.235.240.0/20 + priority: 100 + target_resources: null + target_service_accounts: null + module.folder1.google_folder.folder[0]: + display_name: policy-container + parent: organizations/1122334455 + module.folder2.google_compute_firewall_policy_association.association["iap-policy"]: {} + module.folder2.google_folder.folder[0]: + display_name: hf2 + parent: organizations/1122334455 + +counts: + google_compute_firewall_policy: 1 + google_compute_firewall_policy_association: 2 + google_compute_firewall_policy_rule: 2 + google_folder: 2 diff --git a/tests/modules/folder/examples/iam.yaml b/tests/modules/folder/examples/iam.yaml new file mode 100644 index 000000000..6f0fe2e51 --- /dev/null +++ b/tests/modules/folder/examples/iam.yaml @@ -0,0 +1,59 @@ +# Copyright 2022 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. + +values: + module.folder.google_folder.folder[0]: + display_name: Folder name + parent: organizations/1234567890 + module.folder.google_folder_iam_binding.authoritative["roles/owner"]: + condition: [] + members: + - group:cloud-owners@example.org + - user:one@example.org + role: roles/owner + module.folder.google_folder_iam_binding.authoritative["roles/resourcemanager.folderAdmin"]: + condition: [] + members: + - group:cloud-owners@example.org + role: roles/resourcemanager.folderAdmin + module.folder.google_folder_iam_binding.authoritative["roles/resourcemanager.projectCreator"]: + condition: [] + members: + - group:cloud-owners@example.org + role: roles/resourcemanager.projectCreator + module.folder.google_folder_iam_member.additive["roles/compute.admin-user:a1@example.org"]: + condition: [] + member: user:a1@example.org + role: roles/compute.admin + module.folder.google_folder_iam_member.additive["roles/compute.admin-user:a2@example.org"]: + condition: [] + member: user:a2@example.org + role: roles/compute.admin + module.folder.google_folder_iam_member.additive["roles/compute.viewer-user:a2@example.org"]: + condition: [] + member: user:a2@example.org + role: roles/compute.viewer + module.folder.google_folder_iam_member.additive["roles/storage.admin-user:am1@example.org"]: + condition: [] + member: user:am1@example.org + role: roles/storage.admin + module.folder.google_folder_iam_member.additive["roles/storage.objectViewer-user:am2@example.org"]: + condition: [] + member: user:am2@example.org + role: roles/storage.objectViewer + +counts: + google_folder: 1 + google_folder_iam_binding: 3 + google_folder_iam_member: 5 diff --git a/tests/modules/folder/examples/logging.yaml b/tests/modules/folder/examples/logging.yaml new file mode 100644 index 000000000..79b0e0078 --- /dev/null +++ b/tests/modules/folder/examples/logging.yaml @@ -0,0 +1,75 @@ +# Copyright 2022 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. + +values: + module.folder-sink.google_bigquery_dataset_iam_member.bq-sinks-binding["info"]: + role: roles/bigquery.dataEditor + module.folder-sink.google_folder.folder[0]: + display_name: my-folder + parent: folders/657104291943 + module.folder-sink.google_logging_folder_exclusion.logging-exclusion["no-gce-instances"]: + description: no-gce-instances (Terraform-managed). + filter: resource.type=gce_instance + name: no-gce-instances + module.folder-sink.google_logging_folder_sink.sink["debug"]: + disabled: false + exclusions: + - description: null + disabled: false + filter: logName:compute + name: no-compute + filter: severity=DEBUG + include_children: true + name: debug + module.folder-sink.google_logging_folder_sink.sink["info"]: + disabled: false + exclusions: [] + filter: severity=INFO + include_children: true + name: info + module.folder-sink.google_logging_folder_sink.sink["notice"]: + disabled: false + exclusions: [] + filter: severity=NOTICE + include_children: true + name: notice + module.folder-sink.google_logging_folder_sink.sink["warnings"]: + description: warnings (Terraform-managed). + destination: storage.googleapis.com/gcs_sink + disabled: false + exclusions: [] + filter: severity=WARNING + include_children: true + name: warnings + module.folder-sink.google_project_iam_member.bucket-sinks-binding["debug"]: + condition: + - title: debug bucket writer + role: roles/logging.bucketWriter + module.folder-sink.google_pubsub_topic_iam_member.pubsub-sinks-binding["notice"]: + condition: [] + role: roles/pubsub.publisher + module.folder-sink.google_storage_bucket_iam_member.gcs-sinks-binding["warnings"]: + bucket: gcs_sink + condition: [] + role: roles/storage.objectCreator + +counts: + google_bigquery_dataset_iam_member: 1 + google_folder: 1 + google_logging_folder_exclusion: 1 + google_logging_folder_sink: 4 + google_logging_project_bucket_config: 1 + google_project_iam_member: 1 + google_pubsub_topic_iam_member: 1 + google_storage_bucket_iam_member: 1 diff --git a/tests/modules/folder/examples/org-policies.yaml b/tests/modules/folder/examples/org-policies.yaml new file mode 100644 index 000000000..f8bf41879 --- /dev/null +++ b/tests/modules/folder/examples/org-policies.yaml @@ -0,0 +1,108 @@ +# Copyright 2022 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. + +values: + module.folder.google_folder.folder[0]: + display_name: Folder name + parent: organizations/1234567890 + module.folder.google_org_policy_policy.default["compute.disableGuestAttributesAccess"]: + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + values: [] + module.folder.google_org_policy_policy.default["constraints/compute.skipDefaultNetworkCreation"]: + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + values: [] + module.folder.google_org_policy_policy.default["constraints/compute.trustedImageProjects"]: + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: null + values: + - allowed_values: + - projects/my-project + denied_values: null + module.folder.google_org_policy_policy.default["constraints/compute.vmExternalIpAccess"]: + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: 'TRUE' + enforce: null + values: [] + module.folder.google_org_policy_policy.default["constraints/iam.allowedPolicyMemberDomains"]: + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: null + values: + - allowed_values: + - C0xxxxxxx + - C0yyyyyyy + denied_values: null + module.folder.google_org_policy_policy.default["iam.disableServiceAccountKeyCreation"]: + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + values: [] + module.folder.google_org_policy_policy.default["iam.disableServiceAccountKeyUpload"]: + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: + - description: test condition + expression: resource.matchTagId("tagKeys/1234", "tagValues/1234") + location: somewhere + title: condition + deny_all: null + enforce: 'TRUE' + values: [] + - allow_all: null + condition: [] + deny_all: null + enforce: 'FALSE' + values: [] + +counts: + google_folder: 1 + google_org_policy_policy: 7 diff --git a/tests/modules/folder/examples/tags.yaml b/tests/modules/folder/examples/tags.yaml new file mode 100644 index 000000000..047fea06d --- /dev/null +++ b/tests/modules/folder/examples/tags.yaml @@ -0,0 +1,41 @@ +# Copyright 2022 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. + + +tests/examples/test_plan.py::test_example[modules/folder:Tags] values: + module.folder.google_folder.folder[0]: + display_name: Test + parent: organizations/1122334455 + module.folder.google_tags_tag_binding.binding["env-prod"]: {} + module.folder.google_tags_tag_binding.binding["foo"]: + tag_value: tagValues/12345678 + module.org.google_tags_tag_key.default["environment"]: + description: Environment specification. + parent: organizations/1122334455 + purpose: null + purpose_data: null + short_name: environment + timeouts: null + module.org.google_tags_tag_value.default["environment/dev"]: + description: Managed by the Terraform organization module. + short_name: dev + module.org.google_tags_tag_value.default["environment/prod"]: + description: Managed by the Terraform organization module. + short_name: prod + +counts: + google_folder: 1 + google_tags_tag_binding: 2 + google_tags_tag_key: 1 + google_tags_tag_value: 2 diff --git a/tests/modules/folder/fixture/main.tf b/tests/modules/folder/fixture/main.tf deleted file mode 100644 index a347f61bb..000000000 --- a/tests/modules/folder/fixture/main.tf +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright 2022 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. - */ - -module "test" { - source = "../../../../modules/folder" - parent = "organizations/12345678" - name = "folder-a" - group_iam = var.group_iam - iam = var.iam - iam_additive = var.iam_additive - iam_additive_members = var.iam_additive_members - firewall_policies = var.firewall_policies - firewall_policy_association = var.firewall_policy_association - logging_sinks = var.logging_sinks - logging_exclusions = var.logging_exclusions - org_policies = var.org_policies - org_policies_data_path = var.org_policies_data_path -} diff --git a/tests/modules/folder/fixture/test.logging-sinks.tfvars b/tests/modules/folder/fixture/test.logging-sinks.tfvars deleted file mode 100644 index 95a272e1f..000000000 --- a/tests/modules/folder/fixture/test.logging-sinks.tfvars +++ /dev/null @@ -1,29 +0,0 @@ -logging_sinks = { - warning = { - destination = "mybucket" - type = "storage" - filter = "severity=WARNING" - } - info = { - destination = "projects/myproject/datasets/mydataset" - type = "bigquery" - filter = "severity=INFO" - disabled = true - } - notice = { - destination = "projects/myproject/topics/mytopic" - type = "pubsub" - filter = "severity=NOTICE" - include_children = false - } - debug = { - destination = "projects/myproject/locations/global/buckets/mybucket" - type = "logging" - filter = "severity=DEBUG" - include_children = false - exclusions = { - no-compute = "logName:compute" - no-container = "logName:container" - } - } -} diff --git a/tests/modules/folder/fixture/variables.tf b/tests/modules/folder/fixture/variables.tf deleted file mode 100644 index e2d7a293b..000000000 --- a/tests/modules/folder/fixture/variables.tf +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright 2022 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. - */ - -variable "group_iam" { - type = any - default = {} -} - -variable "iam" { - type = any - default = {} -} - -variable "iam_additive" { - type = any - default = {} -} - -variable "iam_additive_members" { - type = any - default = {} -} - -variable "firewall_policies" { - type = any - default = {} -} - -variable "firewall_policy_association" { - type = any - default = {} -} - -variable "logging_sinks" { - type = any - default = {} -} - -variable "logging_exclusions" { - type = any - default = {} -} - -variable "org_policies" { - type = any - default = {} -} - -variable "org_policies_data_path" { - type = any - default = null -} diff --git a/tests/modules/folder/fixture/test.orgpolicies-boolean.tfvars b/tests/modules/folder/org_policies_boolean.tfvars similarity index 100% rename from tests/modules/folder/fixture/test.orgpolicies-boolean.tfvars rename to tests/modules/folder/org_policies_boolean.tfvars diff --git a/tests/modules/folder/fixture/test.orgpolicies-list.tfvars b/tests/modules/folder/org_policies_list.tfvars similarity index 100% rename from tests/modules/folder/fixture/test.orgpolicies-list.tfvars rename to tests/modules/folder/org_policies_list.tfvars diff --git a/tests/modules/folder/test_plan.py b/tests/modules/folder/test_plan.py deleted file mode 100644 index 0ce1ae4a8..000000000 --- a/tests/modules/folder/test_plan.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 2022 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. - - -def test_folder(plan_runner): - "Test folder resources." - _, resources = plan_runner() - assert len(resources) == 1 - resource = resources[0] - assert resource['type'] == 'google_folder' - assert resource['values']['display_name'] == 'folder-a' - assert resource['values']['parent'] == 'organizations/12345678' - - -def test_iam(plan_runner): - "Test IAM." - group_iam = ( - '{' - '"owners@example.org" = ["roles/owner", "roles/resourcemanager.folderAdmin"],' - '"viewers@example.org" = ["roles/viewer"]' - '}') - iam = ('{' - '"roles/owner" = ["user:one@example.org", "user:two@example.org"],' - '"roles/browser" = ["domain:example.org"]' - '}') - _, resources = plan_runner(group_iam=group_iam, iam=iam) - roles = sorted([(r['values']['role'], sorted(r['values']['members'])) - for r in resources - if r['type'] == 'google_folder_iam_binding']) - assert roles == [ - ('roles/browser', ['domain:example.org']), - ('roles/owner', [ - 'group:owners@example.org', 'user:one@example.org', - 'user:two@example.org' - ]), - ('roles/resourcemanager.folderAdmin', ['group:owners@example.org']), - ('roles/viewer', ['group:viewers@example.org']), - ] - - -def test_iam_multiple_roles(plan_runner): - "Test folder resources with multiple iam roles." - iam = ('{ ' - '"roles/owner" = ["user:a@b.com"], ' - '"roles/viewer" = ["user:c@d.com"] ' - '} ') - _, resources = plan_runner(iam=iam) - assert len(resources) == 3 - - -def test_iam_additive_members(plan_runner): - "Test IAM additive members." - iam = ('{"user:one@example.org" = ["roles/owner"],' - '"user:two@example.org" = ["roles/owner", "roles/editor"]}') - _, resources = plan_runner(iam_additive_members=iam) - roles = set((r['values']['role'], r['values']['member']) - for r in resources - if r['type'] == 'google_folder_iam_member') - assert roles == set([('roles/owner', 'user:one@example.org'), - ('roles/owner', 'user:two@example.org'), - ('roles/editor', 'user:two@example.org')]) diff --git a/tests/modules/folder/test_plan_firewall_policy.py b/tests/modules/folder/test_plan_firewall_policy.py deleted file mode 100644 index 4364fbdf1..000000000 --- a/tests/modules/folder/test_plan_firewall_policy.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright 2022 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. - -def test_firweall_policy(plan_runner): - "Test boolean folder policy." - policy = """ - { - policy1 = { - allow-ingress = { - description = "" - direction = "INGRESS" - action = "allow" - priority = 100 - ranges = ["10.0.0.0/8"] - ports = { - tcp = ["22"] - } - target_service_accounts = null - target_resources = null - logging = false - } - deny-egress = { - description = "" - direction = "EGRESS" - action = "deny" - priority = 200 - ranges = ["192.168.0.0/24"] - ports = { - tcp = ["443"] - } - target_service_accounts = null - target_resources = null - logging = false - } - } - } - """ - association = '{policy1="policy1"}' - _, resources = plan_runner(firewall_policies=policy, - firewall_policy_association=association) - assert len(resources) == 5 - - policies = [r for r in resources - if r['type'] == 'google_compute_firewall_policy'] - assert len(policies) == 1 - - rules = [r for r in resources - if r['type'] == 'google_compute_firewall_policy_rule'] - assert len(rules) == 2 - - rule_values = [] - for rule in rules: - name = rule['name'] - index = rule['index'] - action = rule['values']['action'] - direction = rule['values']['direction'] - priority = rule['values']['priority'] - match = rule['values']['match'] - rule_values.append((name, index, action, direction, priority, match)) - - assert sorted(rule_values) == sorted([ - ('rule', 'policy1-allow-ingress', 'allow', 'INGRESS', 100, [ - { - 'dest_ip_ranges': None, - 'layer4_configs': [{'ip_protocol': 'tcp', 'ports': ['22']}], - 'src_ip_ranges': ['10.0.0.0/8'] - }]), - ('rule', 'policy1-deny-egress', 'deny', 'EGRESS', 200, [ - { - 'dest_ip_ranges': ['192.168.0.0/24'], - 'layer4_configs': [{'ip_protocol': 'tcp', 'ports': ['443']}], - 'src_ip_ranges': None - }]) - ]) diff --git a/tests/modules/folder/test_plan_logging.py b/tests/modules/folder/test_plan_logging.py deleted file mode 100644 index 6b305d0b1..000000000 --- a/tests/modules/folder/test_plan_logging.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright 2022 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. - -from collections import Counter - - -def test_sinks(plan_runner): - "Test folder-level sinks." - tfvars = 'test.logging-sinks.tfvars' - _, resources = plan_runner(tf_var_file=tfvars) - assert len(resources) == 9 - - resource_types = Counter([r["type"] for r in resources]) - assert resource_types == { - "google_logging_folder_sink": 4, - "google_folder": 1, - "google_bigquery_dataset_iam_member": 1, - "google_project_iam_member": 1, - "google_pubsub_topic_iam_member": 1, - "google_storage_bucket_iam_member": 1, - } - - sinks = [r for r in resources if r["type"] == "google_logging_folder_sink"] - assert sorted([r["index"] for r in sinks]) == [ - "debug", - "info", - "notice", - "warning", - ] - values = [( - r["index"], - r["values"]["filter"], - r["values"]["destination"], - r["values"]["description"], - r["values"]["include_children"], - r["values"]["disabled"], - ) for r in sinks] - assert sorted(values) == [ - ("debug", "severity=DEBUG", - "logging.googleapis.com/projects/myproject/locations/global/buckets/mybucket", - "debug (Terraform-managed).", False, False), - ("info", "severity=INFO", - "bigquery.googleapis.com/projects/myproject/datasets/mydataset", - "info (Terraform-managed).", True, True), - ("notice", "severity=NOTICE", - "pubsub.googleapis.com/projects/myproject/topics/mytopic", - "notice (Terraform-managed).", False, False), - ("warning", "severity=WARNING", "storage.googleapis.com/mybucket", - "warning (Terraform-managed).", True, False), - ] - - bindings = [r for r in resources if "member" in r["type"]] - values = [(r["index"], r["type"], r["values"]["role"], - r["values"]["condition"]) for r in bindings] - assert sorted(values) == [ - ("debug", "google_project_iam_member", "roles/logging.bucketWriter", [{ - 'expression': - "resource.name.endsWith('projects/myproject/locations/global/buckets/mybucket')", - 'title': - 'debug bucket writer' - }]), - ("info", "google_bigquery_dataset_iam_member", - "roles/bigquery.dataEditor", []), - ("notice", "google_pubsub_topic_iam_member", "roles/pubsub.publisher", - []), - ("warning", "google_storage_bucket_iam_member", - "roles/storage.objectCreator", []), - ] - - exclusions = [(r["index"], r["values"]["exclusions"]) for r in sinks] - assert sorted(exclusions) == [ - ("debug", [{ - "description": None, - "disabled": False, - "filter": "logName:compute", - "name": "no-compute" - }, { - "description": None, - "disabled": False, - "filter": "logName:container", - "name": "no-container" - }]), - ("info", []), - ("notice", []), - ("warning", []), - ] - - -def test_exclusions(plan_runner): - "Test folder-level logging exclusions." - logging_exclusions = ("{" - 'exclusion1 = "resource.type=gce_instance", ' - 'exclusion2 = "severity=NOTICE", ' - "}") - _, resources = plan_runner(logging_exclusions=logging_exclusions) - assert len(resources) == 3 - exclusions = [ - r for r in resources if r["type"] == "google_logging_folder_exclusion" - ] - assert sorted([r["index"] for r in exclusions]) == [ - "exclusion1", - "exclusion2", - ] - values = [(r["index"], r["values"]["filter"]) for r in exclusions] - assert sorted(values) == [ - ("exclusion1", "resource.type=gce_instance"), - ("exclusion2", "severity=NOTICE"), - ] diff --git a/tests/modules/folder/test_plan_org_policies.py b/tests/modules/folder/test_plan_org_policies.py index 8463761e8..161845376 100644 --- a/tests/modules/folder/test_plan_org_policies.py +++ b/tests/modules/folder/test_plan_org_policies.py @@ -12,33 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .validate_policies import validate_policy_boolean, validate_policy_list +import pytest + +_params = ['boolean', 'list'] -def test_policy_boolean(plan_runner): - "Test boolean org policy." - tfvars = 'test.orgpolicies-boolean.tfvars' - _, resources = plan_runner(tf_var_file=tfvars) - validate_policy_boolean(resources) - - -def test_policy_list(plan_runner): - "Test list org policy." - tfvars = 'test.orgpolicies-list.tfvars' - _, resources = plan_runner(tf_var_file=tfvars) - validate_policy_list(resources) - - -def test_factory_policy_boolean(plan_runner, tfvars_to_yaml, tmp_path): +@pytest.mark.parametrize('policy_type', _params) +def test_policy_factory(plan_summary, tfvars_to_yaml, tmp_path, policy_type): dest = tmp_path / 'policies.yaml' - tfvars_to_yaml('fixture/test.orgpolicies-boolean.tfvars', dest, - 'org_policies') - _, resources = plan_runner(org_policies_data_path=f'"{tmp_path}"') - validate_policy_boolean(resources) - - -def test_factory_policy_list(plan_runner, tfvars_to_yaml, tmp_path): - dest = tmp_path / 'policies.yaml' - tfvars_to_yaml('fixture/test.orgpolicies-list.tfvars', dest, 'org_policies') - _, resources = plan_runner(org_policies_data_path=f'"{tmp_path}"') - validate_policy_list(resources) + tfvars_to_yaml(f'org_policies_{policy_type}.tfvars', dest, 'org_policies') + tfvars_plan = plan_summary( + 'modules/folder', + tf_var_files=['common.tfvars', f'org_policies_{policy_type}.tfvars']) + yaml_plan = plan_summary('modules/folder', tf_var_files=['common.tfvars'], + org_policies_data_path=f'{tmp_path}') + assert tfvars_plan.values == yaml_plan.values diff --git a/tests/modules/folder/validate_policies.py b/tests/modules/folder/validate_policies.py deleted file mode 100644 index 385898b17..000000000 --- a/tests/modules/folder/validate_policies.py +++ /dev/null @@ -1,158 +0,0 @@ -# Copyright 2022 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. - - -def validate_policy_boolean(resources): - assert len(resources) == 3 - policies = [r for r in resources if r['type'] == 'google_org_policy_policy'] - assert len(policies) == 2 - - p1 = [ - r['values']['spec'][0] - for r in policies - if r['index'] == 'iam.disableServiceAccountKeyCreation' - ][0] - - assert p1['inherit_from_parent'] is None - assert p1['reset'] is None - assert p1['rules'] == [{ - 'allow_all': None, - 'condition': [], - 'deny_all': None, - 'enforce': 'TRUE', - 'values': [] - }] - - p2 = [ - r['values']['spec'][0] - for r in policies - if r['index'] == 'iam.disableServiceAccountKeyUpload' - ][0] - - assert p2['inherit_from_parent'] is None - assert p2['reset'] is None - assert len(p2['rules']) == 2 - assert p2['rules'][0] == { - 'allow_all': None, - 'condition': [], - 'deny_all': None, - 'enforce': 'FALSE', - 'values': [] - } - assert p2['rules'][1] == { - 'allow_all': None, - 'condition': [{ - 'description': 'test condition', - 'expression': 'resource.matchTagId(aa, bb)', - 'location': 'xxx', - 'title': 'condition' - }], - 'deny_all': None, - 'enforce': 'TRUE', - 'values': [] - } - - -def validate_policy_list(resources): - assert len(resources) == 4 - - policies = [r for r in resources if r['type'] == 'google_org_policy_policy'] - assert len(policies) == 3 - - p1 = [ - r['values']['spec'][0] - for r in policies - if r['index'] == 'compute.vmExternalIpAccess' - ][0] - assert p1['inherit_from_parent'] is None - assert p1['reset'] is None - assert p1['rules'] == [{ - 'allow_all': None, - 'condition': [], - 'deny_all': 'TRUE', - 'enforce': None, - 'values': [] - }] - - p2 = [ - r['values']['spec'][0] - for r in policies - if r['index'] == 'iam.allowedPolicyMemberDomains' - ][0] - assert p2['inherit_from_parent'] is None - assert p2['reset'] is None - assert p2['rules'] == [{ - 'allow_all': - None, - 'condition': [], - 'deny_all': - None, - 'enforce': - None, - 'values': [{ - 'allowed_values': [ - 'C0xxxxxxx', - 'C0yyyyyyy', - ], - 'denied_values': None - }] - }] - - p3 = [ - r['values']['spec'][0] - for r in policies - if r['index'] == 'compute.restrictLoadBalancerCreationForTypes' - ][0] - assert p3['inherit_from_parent'] is None - assert p3['reset'] is None - assert len(p3['rules']) == 3 - assert p3['rules'][0] == { - 'allow_all': None, - 'condition': [], - 'deny_all': None, - 'enforce': None, - 'values': [{ - 'allowed_values': None, - 'denied_values': ['in:EXTERNAL'] - }] - } - - assert p3['rules'][1] == { - 'allow_all': None, - 'condition': [{ - 'description': 'test condition', - 'expression': 'resource.matchTagId(aa, bb)', - 'location': 'xxx', - 'title': 'condition' - }], - 'deny_all': None, - 'enforce': None, - 'values': [{ - 'allowed_values': ['EXTERNAL_1'], - 'denied_values': None - }] - } - - assert p3['rules'][2] == { - 'allow_all': 'TRUE', - 'condition': [{ - 'description': 'test condition2', - 'expression': 'resource.matchTagId(cc, dd)', - 'location': 'xxx', - 'title': 'condition2' - }], - 'deny_all': None, - 'enforce': None, - 'values': [] - } diff --git a/tests/modules/logging_bucket/test_plan.py b/tests/modules/logging_bucket/test_plan.py index e3cf159ff..8ec685add 100644 --- a/tests/modules/logging_bucket/test_plan.py +++ b/tests/modules/logging_bucket/test_plan.py @@ -12,10 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. + def test_project_logging_bucket(plan_runner): "Test project logging bucket." - _, resources = plan_runner(parent_type="project", - parent="myproject") + _, resources = plan_runner(parent_type="project", parent="myproject") assert len(resources) == 1 resource = resources[0] @@ -31,9 +31,7 @@ def test_project_logging_bucket(plan_runner): def test_folder_logging_bucket(plan_runner): "Test project logging bucket." - _, resources = plan_runner( - parent_type="folder", parent="folders/0123456789" - ) + _, resources = plan_runner(parent_type="folder", parent="folders/0123456789") assert len(resources) == 1 resource = resources[0] @@ -49,9 +47,8 @@ def test_folder_logging_bucket(plan_runner): def test_organization_logging_bucket(plan_runner): "Test project logging bucket." - _, resources = plan_runner( - parent_type="organization", parent="organizations/0123456789" - ) + _, resources = plan_runner(parent_type="organization", + parent="organizations/0123456789") assert len(resources) == 1 resource = resources[0] @@ -67,9 +64,7 @@ def test_organization_logging_bucket(plan_runner): def test_billing_account_logging_bucket(plan_runner): "Test project logging bucket." - _, resources = plan_runner( - parent_type="billing_account", parent="0123456789" - ) + _, resources = plan_runner(parent_type="billing_account", parent="0123456789") assert len(resources) == 1 resource = resources[0] diff --git a/tests/modules/organization/examples/basic.yaml b/tests/modules/organization/examples/basic.yaml index bcd12386e..2ba70f40a 100644 --- a/tests/modules/organization/examples/basic.yaml +++ b/tests/modules/organization/examples/basic.yaml @@ -99,11 +99,6 @@ values: - inherit_from_parent: null reset: null rules: - - allow_all: null - condition: [] - deny_all: null - enforce: 'FALSE' - values: [] - allow_all: null condition: - description: test condition @@ -113,6 +108,11 @@ values: deny_all: null enforce: 'TRUE' values: [] + - allow_all: null + condition: [] + deny_all: null + enforce: 'FALSE' + values: [] module.org.google_organization_iam_binding.authoritative["roles/owner"]: condition: [] members: diff --git a/tests/modules/organization/org_policies_boolean.yaml b/tests/modules/organization/org_policies_boolean.yaml index 310997a4c..00f98b06c 100644 --- a/tests/modules/organization/org_policies_boolean.yaml +++ b/tests/modules/organization/org_policies_boolean.yaml @@ -33,11 +33,6 @@ values: - inherit_from_parent: null reset: null rules: - - allow_all: null - condition: [] - deny_all: null - enforce: 'FALSE' - values: [] - allow_all: null condition: - description: test condition @@ -47,6 +42,11 @@ values: deny_all: null enforce: 'TRUE' values: [] + - allow_all: null + condition: [] + deny_all: null + enforce: 'FALSE' + values: [] timeouts: null counts: diff --git a/tests/modules/organization/org_policies_list.yaml b/tests/modules/organization/org_policies_list.yaml index 39c3a3896..393eadde4 100644 --- a/tests/modules/organization/org_policies_list.yaml +++ b/tests/modules/organization/org_policies_list.yaml @@ -20,14 +20,6 @@ values: - inherit_from_parent: null reset: null rules: - - allow_all: null - condition: [] - deny_all: null - enforce: null - values: - - allowed_values: null - denied_values: - - in:EXTERNAL - allow_all: null condition: - description: test condition @@ -49,6 +41,14 @@ values: deny_all: null enforce: null values: [] + - allow_all: null + condition: [] + deny_all: null + enforce: null + values: + - allowed_values: null + denied_values: + - in:EXTERNAL timeouts: null google_org_policy_policy.default["compute.vmExternalIpAccess"]: name: organizations/1234567890/policies/compute.vmExternalIpAccess diff --git a/tests/modules/project/examples/org-policies.yaml b/tests/modules/project/examples/org-policies.yaml index 38e0ba9b9..8841dedee 100644 --- a/tests/modules/project/examples/org-policies.yaml +++ b/tests/modules/project/examples/org-policies.yaml @@ -99,11 +99,6 @@ values: - inherit_from_parent: null reset: null rules: - - allow_all: null - condition: [] - deny_all: null - enforce: 'FALSE' - values: [] - allow_all: null condition: - description: test condition @@ -113,6 +108,11 @@ values: deny_all: null enforce: 'TRUE' values: [] + - allow_all: null + condition: [] + deny_all: null + enforce: 'FALSE' + values: [] module.project.google_project.project[0]: billing_account: 123456-123456-123456 folder_id: '1234567890' diff --git a/tests/modules/project/org_policies_boolean.yaml b/tests/modules/project/org_policies_boolean.yaml index 44cba34d0..4f23958fb 100644 --- a/tests/modules/project/org_policies_boolean.yaml +++ b/tests/modules/project/org_policies_boolean.yaml @@ -33,11 +33,6 @@ values: - inherit_from_parent: null reset: null rules: - - allow_all: null - condition: [] - deny_all: null - enforce: 'FALSE' - values: [] - allow_all: null condition: - description: test condition @@ -47,6 +42,11 @@ values: deny_all: null enforce: 'TRUE' values: [] + - allow_all: null + condition: [] + deny_all: null + enforce: 'FALSE' + values: [] timeouts: null counts: diff --git a/tests/modules/project/org_policies_list.yaml b/tests/modules/project/org_policies_list.yaml index ab556a104..2f1c64e0b 100644 --- a/tests/modules/project/org_policies_list.yaml +++ b/tests/modules/project/org_policies_list.yaml @@ -20,14 +20,6 @@ values: - inherit_from_parent: null reset: null rules: - - allow_all: null - condition: [] - deny_all: null - enforce: null - values: - - allowed_values: null - denied_values: - - in:EXTERNAL - allow_all: null condition: - description: test condition @@ -49,6 +41,14 @@ values: deny_all: null enforce: null values: [] + - allow_all: null + condition: [] + deny_all: null + enforce: null + values: + - allowed_values: null + denied_values: + - in:EXTERNAL timeouts: null google_org_policy_policy.default["compute.vmExternalIpAccess"]: name: projects/my-project/policies/compute.vmExternalIpAccess