Migrate project module to new tests

This commit is contained in:
Julio Castillo 2022-12-16 16:44:29 +01:00
parent e700a27079
commit 4b77e484b1
40 changed files with 957 additions and 788 deletions

View File

@ -2,6 +2,23 @@
This module implements the creation and management of one GCP project including IAM, organization policies, Shared VPC host or service attachment, service API activation, and tag attachment. It also offers a convenient way to refer to managed service identities (aka robot service accounts) for APIs.
# Basic Project Creation
```hcl
module "project" {
source = "./fabric/modules/project"
billing_account = "123456-123456-123456"
name = "myproject"
parent = "folders/1234567890"
prefix = "foo"
services = [
"container.googleapis.com",
"stackdriver.googleapis.com"
]
}
# tftest modules=1 resources=3 inventory=basic.yaml
```
## IAM Examples
IAM is managed via several variables that implement different levels of control:
@ -36,7 +53,7 @@ module "project" {
]
}
}
# tftest modules=1 resources=4
# tftest modules=1 resources=4 inventory=iam-authoritative.yaml
```
The `group_iam` variable uses group email addresses as keys and is a convenient way to assign roles to humans following Google's best practices. The end result is readable code that also serves as documentation.
@ -48,10 +65,6 @@ module "project" {
name = "project-example"
parent = "folders/1234567890"
prefix = "foo"
services = [
"container.googleapis.com",
"stackdriver.googleapis.com"
]
group_iam = {
"gcp-security-admins@example.com" = [
"roles/cloudasset.owner",
@ -61,7 +74,7 @@ module "project" {
]
}
}
# tftest modules=1 resources=7
# tftest modules=1 resources=5 inventory=iam-group.yaml
```
### Additive IAM
@ -85,7 +98,22 @@ module "project" {
],
}
}
# tftest modules=1 resources=5 inventory=additive.yaml
# tftest modules=1 resources=5 inventory=iam-additive.yaml
```
### Additive IAM by members
```hcl
module "project" {
source = "./fabric/modules/project"
name = "project-example"
iam_additive_members = {
"user:one@example.org" = ["roles/owner"]
"user:two@example.org" = ["roles/owner", "roles/editor"]
}
}
# tftest modules=1 resources=4 inventory=iam-additive-members.yaml
```
### Service Identities and authoritative IAM
@ -110,34 +138,27 @@ module "project" {
# tftest modules=1 resources=2
```
## Shared VPC service
## Shared VPC
The module allows managing Shared VPC status for both hosts and service projects, and includes a simple way of assigning Shared VPC roles to service identities.
### Host project
You can enable Shared VPC Host at the project level and manage project service association independently.
```hcl
module "project" {
module "host-project" {
source = "./fabric/modules/project"
name = "project-example"
name = "my-host-project"
shared_vpc_host_config = {
enabled = true
}
}
# tftest modules=1 resources=2
```
### Service project
```hcl
module "project" {
module "service-project" {
source = "./fabric/modules/project"
name = "project-example"
name = "my-service-project"
shared_vpc_service_config = {
attach = true
host_project = "my-host-project"
host_project = module.host-project.project_id
service_identity_iam = {
"roles/compute.networkUser" = [
"cloudservices", "container-engine"
@ -151,7 +172,7 @@ module "project" {
}
}
}
# tftest modules=1 resources=6
# tftest modules=2 resources=8 inventory=shared-vpc.yaml
```
## Organization policies
@ -165,10 +186,6 @@ module "project" {
name = "project-example"
parent = "folders/1234567890"
prefix = "foo"
services = [
"container.googleapis.com",
"stackdriver.googleapis.com"
]
org_policies = {
"compute.disableGuestAttributesAccess" = {
enforce = true
@ -208,7 +225,7 @@ module "project" {
}
}
}
# tftest modules=1 resources=10
# tftest modules=1 resources=8 inventory=org-policies.yaml
```
### Organization policy factory
@ -220,63 +237,54 @@ Note that contraints defined via `org_policies` take precedence over those in `o
The example below deploys a few organization policies split between two YAML files.
```hcl
module "folder" {
source = "./fabric/modules/folder"
parent = "organizations/1234567890"
name = "Folder name"
module "project" {
source = "./fabric/modules/project"
billing_account = "123456-123456-123456"
name = "project-example"
parent = "folders/1234567890"
prefix = "foo"
org_policies_data_path = "configs/org-policies/"
}
# tftest modules=1 resources=6 files=boolean,list
# tftest modules=1 resources=8 files=boolean,list inventory=org-policies.yaml
```
```yaml
# tftest-file id=boolean path=configs/org-policies/boolean.yaml
compute.disableGuestAttributesAccess:
enforce: true
constraints/compute.skipDefaultNetworkCreation:
enforce: true
iam.disableServiceAccountKeyCreation:
enforce: true
iam.disableServiceAccountKeyUpload:
enforce: false
rules:
- condition:
expression: resource.matchTagId("tagKeys/1234", "tagValues/1234")
title: condition
description: test condition
location: xxx
enforce: true
- condition:
description: test condition
expression: resource.matchTagId("tagKeys/1234", "tagValues/1234")
location: somewhere
title: condition
enforce: true
```
```yaml
# tftest-file id=list path=configs/org-policies/list.yaml
compute.vmExternalIpAccess:
deny:
all: true
iam.allowedPolicyMemberDomains:
constraints/compute.trustedImageProjects:
allow:
values:
- C0xxxxxxx
- C0yyyyyyy
compute.restrictLoadBalancerCreationForTypes:
- projects/my-project
constraints/compute.vmExternalIpAccess:
deny:
values: ["in:EXTERNAL"]
rules:
- condition:
expression: resource.matchTagId("tagKeys/1234", "tagValues/1234")
title: condition
description: test condition
allow:
values: ["in:EXTERNAL"]
- condition:
expression: resource.matchTagId("tagKeys/12345", "tagValues/12345")
title: condition2
description: test condition2
allow:
all: true
all: true
constraints/iam.allowedPolicyMemberDomains:
allow:
values:
- C0xxxxxxx
- C0yyyyyyy
```
## Logging Sinks (in same project)
## Logging Sinks
```hcl
module "gcs" {
@ -339,49 +347,18 @@ module "project-host" {
no-gce-instances = "resource.type=gce_instance"
}
}
# tftest modules=5 resources=14
# tftest modules=5 resources=14 inventory=logging.yaml
```
## Logging Sinks (in different project)
When writing to destinations in a different project, set `unique_writer` to `true`.
```hcl
module "gcs" {
source = "./fabric/modules/gcs"
project_id = "project-1"
name = "gcs_sink"
force_destroy = true
}
module "project-host" {
source = "./fabric/modules/project"
name = "project-2"
billing_account = "123456-123456-123456"
parent = "folders/1234567890"
logging_sinks = {
warnings = {
destination = module.gcs.id
filter = "severity=WARNING"
unique_writer = true
type = "storage"
}
}
}
# tftest modules=2 resources=4
```
## Cloud KMS encryption keys
The module offers a simple, centralized way to assign `roles/cloudkms.cryptoKeyEncrypterDecrypter` to service identities.
```hcl
module "project" {
source = "./fabric/modules/project"
name = "my-project"
billing_account = "123456-123456-123456"
prefix = "foo"
source = "./fabric/modules/project"
name = "my-project"
prefix = "foo"
services = [
"compute.googleapis.com",
"storage.googleapis.com"
@ -448,7 +425,7 @@ module "project" {
output "compute_robot" {
value = module.project.service_accounts.robots.compute
}
# tftest modules=1 resources=2
# tftest modules=1 resources=2 inventory:outputs.yaml
```
<!-- TFDOC OPTS files:1 -->

View File

@ -19,7 +19,7 @@ variable "bucket" {
}
variable "billing_account_id" {
default = "billing_account_id"
default = "123456-123456-123456"
}
variable "kms_key" {

View File

@ -12,8 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import pathlib
import pytest
_params = ['boolean', 'list']

View File

@ -0,0 +1 @@
name = "my-project"

View File

@ -0,0 +1,39 @@
# 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.project.google_project.project[0]:
auto_create_network: false
billing_account: 123456-123456-123456
folder_id: '1234567890'
labels: null
name: foo-myproject
org_id: null
project_id: foo-myproject
skip_delete: false
module.project.google_project_service.project_services["container.googleapis.com"]:
disable_dependent_services: false
disable_on_destroy: false
project: foo-myproject
service: container.googleapis.com
module.project.google_project_service.project_services["stackdriver.googleapis.com"]:
disable_dependent_services: false
disable_on_destroy: false
project: foo-myproject
service: stackdriver.googleapis.com
counts:
google_project: 1
google_project_service: 2

View File

@ -0,0 +1,36 @@
# 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.project.google_project.project[0]:
project_id: project-example
module.project.google_project_iam_member.additive["roles/editor-user:two@example.org"]:
condition: []
member: user:two@example.org
project: project-example
role: roles/editor
module.project.google_project_iam_member.additive["roles/owner-user:one@example.org"]:
condition: []
member: user:one@example.org
project: project-example
role: roles/owner
module.project.google_project_iam_member.additive["roles/owner-user:two@example.org"]:
condition: []
member: user:two@example.org
project: project-example
role: roles/owner
counts:
google_project: 1
google_project_iam_member: 3

View File

@ -0,0 +1,40 @@
# 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.project.google_project.project[0]: {}
module.project.google_project_iam_member.additive["roles/owner-group:three@example.org"]:
condition: []
member: group:three@example.org
project: project-example
role: roles/owner
module.project.google_project_iam_member.additive["roles/storage.objectAdmin-group:two@example.org"]:
condition: []
member: group:two@example.org
project: project-example
role: roles/storage.objectAdmin
module.project.google_project_iam_member.additive["roles/viewer-group:one@example.org"]:
condition: []
member: group:one@example.org
project: project-example
role: roles/viewer
module.project.google_project_iam_member.additive["roles/viewer-group:two@xample.org"]:
condition: []
member: group:two@xample.org
project: project-example
role: roles/viewer
counts:
google_project: 1
google_project_iam_member: 4

View File

@ -0,0 +1,39 @@
# 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.project.google_project.project[0]: {}
module.project.google_project_iam_binding.authoritative["roles/container.hostServiceAgentUser"]:
condition: []
members:
- serviceAccount:my_gke_service_account
project: foo-project-example
role: roles/container.hostServiceAgentUser
module.project.google_project_service.project_services["container.googleapis.com"]:
disable_dependent_services: false
disable_on_destroy: false
project: foo-project-example
service: container.googleapis.com
timeouts: null
module.project.google_project_service.project_services["stackdriver.googleapis.com"]:
disable_dependent_services: false
disable_on_destroy: false
project: foo-project-example
service: stackdriver.googleapis.com
timeouts: null
counts:
google_project: 1
google_project_iam_binding: 1
google_project_service: 2

View File

@ -0,0 +1,44 @@
# 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.project.google_project.project[0]: {}
module.project.google_project_iam_binding.authoritative["roles/cloudasset.owner"]:
condition: []
members:
- group:gcp-security-admins@example.com
project: foo-project-example
role: roles/cloudasset.owner
module.project.google_project_iam_binding.authoritative["roles/cloudsupport.techSupportEditor"]:
condition: []
members:
- group:gcp-security-admins@example.com
project: foo-project-example
role: roles/cloudsupport.techSupportEditor
module.project.google_project_iam_binding.authoritative["roles/iam.securityReviewer"]:
condition: []
members:
- group:gcp-security-admins@example.com
project: foo-project-example
role: roles/iam.securityReviewer
module.project.google_project_iam_binding.authoritative["roles/logging.admin"]:
condition: []
members:
- group:gcp-security-admins@example.com
project: foo-project-example
role: roles/logging.admin
counts:
google_project: 1
google_project_iam_binding: 4

View File

@ -0,0 +1,38 @@
# 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.org.google_tags_tag_key.default["environment"]:
description: Environment specification.
parent: organizations/1122334455
purpose: null
purpose_data: null
short_name: environment
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
module.project.google_project.project[0]:
project_id: test-project
module.project.google_tags_tag_binding.binding["env-prod"]: {}
module.project.google_tags_tag_binding.binding["foo"]:
tag_value: tagValues/12345678
counts:
google_project: 1
google_tags_tag_binding: 2
google_tags_tag_key: 1
google_tags_tag_value: 2

View File

@ -0,0 +1,94 @@
# 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.project-host.google_bigquery_dataset_iam_member.bq-sinks-binding["info"]:
condition: []
role: roles/bigquery.dataEditor
module.project-host.google_logging_project_exclusion.logging-exclusion["no-gce-instances"]:
description: no-gce-instances (Terraform-managed).
disabled: null
filter: resource.type=gce_instance
name: no-gce-instances
project: my-project
module.project-host.google_logging_project_sink.sink["debug"]:
description: debug (Terraform-managed).
disabled: false
exclusions:
- description: null
disabled: false
filter: logName:compute
name: no-compute
filter: severity=DEBUG
name: debug
project: my-project
unique_writer_identity: false
module.project-host.google_logging_project_sink.sink["info"]:
description: info (Terraform-managed).
disabled: false
exclusions: []
filter: severity=INFO
name: info
project: my-project
unique_writer_identity: false
module.project-host.google_logging_project_sink.sink["notice"]:
description: notice (Terraform-managed).
disabled: false
exclusions: []
filter: severity=NOTICE
name: notice
project: my-project
unique_writer_identity: false
module.project-host.google_logging_project_sink.sink["warnings"]:
description: warnings (Terraform-managed).
destination: storage.googleapis.com/gcs_sink
disabled: false
exclusions: []
filter: severity=WARNING
name: warnings
project: my-project
unique_writer_identity: false
module.project-host.google_project.project[0]:
auto_create_network: false
billing_account: 123456-123456-123456
folder_id: '1234567890'
labels: null
name: my-project
org_id: null
project_id: my-project
skip_delete: false
module.project-host.google_project_iam_member.bucket-sinks-binding["debug"]:
condition:
- title: debug bucket writer
role: roles/logging.bucketWriter
module.project-host.google_pubsub_topic_iam_member.pubsub-sinks-binding["notice"]:
condition: []
role: roles/pubsub.publisher
module.project-host.google_storage_bucket_iam_member.gcs-sinks-binding["warnings"]:
bucket: gcs_sink
condition: []
role: roles/storage.objectCreator
counts:
google_bigquery_dataset: 1
google_bigquery_dataset_iam_member: 1
google_logging_project_bucket_config: 1
google_logging_project_exclusion: 1
google_logging_project_sink: 4
google_project: 1
google_project_iam_member: 1
google_pubsub_topic: 1
google_pubsub_topic_iam_member: 1
google_storage_bucket: 1
google_storage_bucket_iam_member: 1

View File

@ -0,0 +1,125 @@
# 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.project.google_org_policy_policy.default["compute.disableGuestAttributesAccess"]:
name: projects/foo-project-example/policies/compute.disableGuestAttributesAccess
parent: projects/foo-project-example
spec:
- inherit_from_parent: null
reset: null
rules:
- allow_all: null
condition: []
deny_all: null
enforce: 'TRUE'
values: []
module.project.google_org_policy_policy.default["constraints/compute.skipDefaultNetworkCreation"]:
name: projects/foo-project-example/policies/constraints/compute.skipDefaultNetworkCreation
parent: projects/foo-project-example
spec:
- inherit_from_parent: null
reset: null
rules:
- allow_all: null
condition: []
deny_all: null
enforce: 'TRUE'
values: []
module.project.google_org_policy_policy.default["constraints/compute.trustedImageProjects"]:
name: projects/foo-project-example/policies/constraints/compute.trustedImageProjects
parent: projects/foo-project-example
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.project.google_org_policy_policy.default["constraints/compute.vmExternalIpAccess"]:
name: projects/foo-project-example/policies/constraints/compute.vmExternalIpAccess
parent: projects/foo-project-example
spec:
- inherit_from_parent: null
reset: null
rules:
- allow_all: null
condition: []
deny_all: 'TRUE'
enforce: null
values: []
module.project.google_org_policy_policy.default["constraints/iam.allowedPolicyMemberDomains"]:
name: projects/foo-project-example/policies/constraints/iam.allowedPolicyMemberDomains
parent: projects/foo-project-example
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.project.google_org_policy_policy.default["iam.disableServiceAccountKeyCreation"]:
name: projects/foo-project-example/policies/iam.disableServiceAccountKeyCreation
parent: projects/foo-project-example
spec:
- inherit_from_parent: null
reset: null
rules:
- allow_all: null
condition: []
deny_all: null
enforce: 'TRUE'
values: []
module.project.google_org_policy_policy.default["iam.disableServiceAccountKeyUpload"]:
name: projects/foo-project-example/policies/iam.disableServiceAccountKeyUpload
parent: projects/foo-project-example
spec:
- inherit_from_parent: null
reset: null
rules:
- allow_all: null
condition: []
deny_all: null
enforce: 'FALSE'
values: []
- allow_all: null
condition:
- description: test condition
expression: resource.matchTagId("tagKeys/1234", "tagValues/1234")
location: somewhere
title: condition
deny_all: null
enforce: 'TRUE'
values: []
module.project.google_project.project[0]:
billing_account: 123456-123456-123456
folder_id: '1234567890'
name: foo-project-example
org_id: null
project_id: foo-project-example
counts:
google_org_policy_policy: 7
google_project: 1

View File

@ -0,0 +1,27 @@
# 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.project.google_project.project[0]:
project_id: project-example
module.project.google_project_service.project_services["compute.googleapis.com"]:
project: project-example
service: compute.googleapis.com
counts:
google_project: 1
google_project_service: 1
outputs:
compute_robot: __missing__

View File

@ -0,0 +1,46 @@
# 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.host-project.google_compute_shared_vpc_host_project.shared_vpc_host[0]:
project: my-host-project
module.host-project.google_project.project[0]:
project_id: my-host-project
module.service-project.google_compute_shared_vpc_service_project.shared_vpc_service[0]:
host_project: my-host-project
service_project: my-service-project
module.service-project.google_project.project[0]:
project_id: my-service-project
module.service-project.google_project_iam_member.shared_vpc_host_robots["roles/compute.networkUser:cloudservices"]:
condition: []
project: my-host-project
role: roles/compute.networkUser
module.service-project.google_project_iam_member.shared_vpc_host_robots["roles/compute.networkUser:container-engine"]:
condition: []
project: my-host-project
role: roles/compute.networkUser
module.service-project.google_project_iam_member.shared_vpc_host_robots["roles/container.hostServiceAgentUser:container-engine"]:
condition: []
project: my-host-project
role: roles/container.hostServiceAgentUser
module.service-project.google_project_iam_member.shared_vpc_host_robots["roles/vpcaccess.user:cloudrun"]:
condition: []
project: my-host-project
role: roles/vpcaccess.user
counts:
google_compute_shared_vpc_host_project: 1
google_compute_shared_vpc_service_project: 1
google_project: 2
google_project_iam_member: 4

View File

@ -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.
*/
module "test" {
source = "../../../../modules/project"
name = var.name
billing_account = var.billing_account
auto_create_network = var.auto_create_network
custom_roles = var.custom_roles
iam = var.iam
iam_additive = var.iam_additive
iam_additive_members = var.iam_additive_members
labels = var.labels
lien_reason = var.lien_reason
org_policies = var.org_policies
org_policies_data_path = var.org_policies_data_path
oslogin = var.oslogin
oslogin_admins = var.oslogin_admins
oslogin_users = var.oslogin_users
parent = var.parent
prefix = var.prefix
service_encryption_key_ids = var.service_encryption_key_ids
services = var.services
logging_sinks = var.logging_sinks
logging_exclusions = var.logging_exclusions
shared_vpc_host_config = var.shared_vpc_host_config
}
module "test-svpc-service" {
source = "../../../../modules/project"
count = var._test_service_project ? 1 : 0
name = "test-svc"
billing_account = var.billing_account
auto_create_network = false
parent = var.parent
services = var.services
shared_vpc_service_config = {
attach = true
host_project = module.test.project_id
service_identity_iam = {
"roles/compute.networkUser" = [
"cloudservices", "container-engine"
]
"roles/vpcaccess.user" = [
"cloudrun"
]
"roles/container.hostServiceAgentUser" = [
"container-engine"
]
}
}
}

View File

@ -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"
unique_writer = true
}
debug = {
destination = "projects/myproject/locations/global/buckets/mybucket"
type = "logging"
filter = "severity=DEBUG"
exclusions = {
no-compute = "logName:compute"
no-container = "logName:container"
}
unique_writer = true
}
}

View File

@ -1,134 +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 "_test_service_project" {
type = bool
default = false
}
variable "name" {
type = string
default = "my-project"
}
variable "billing_account" {
type = string
default = "12345-12345-12345"
}
variable "auto_create_network" {
type = bool
default = false
}
variable "custom_roles" {
type = map(list(string))
default = {}
}
variable "iam" {
type = map(list(string))
default = {}
}
variable "iam_additive" {
type = map(list(string))
default = {}
}
variable "iam_additive_members" {
type = map(list(string))
default = {}
}
variable "labels" {
type = map(string)
default = {}
}
variable "lien_reason" {
type = string
default = ""
}
variable "org_policies" {
type = any
default = {}
}
variable "org_policies_data_path" {
type = any
default = null
}
variable "oslogin" {
type = bool
default = false
}
variable "oslogin_admins" {
type = list(string)
default = []
}
variable "oslogin_users" {
type = list(string)
default = []
}
variable "parent" {
type = string
default = null
}
variable "prefix" {
type = string
default = null
}
variable "service_encryption_key_ids" {
type = map(list(string))
default = {}
}
variable "services" {
type = list(string)
default = []
}
variable "logging_sinks" {
type = any
default = {}
}
variable "logging_exclusions" {
type = map(string)
default = {}
}
variable "shared_vpc_host_config" {
type = object({
enabled = bool
service_projects = list(string)
})
default = {
enabled = true
service_projects = [
"my-service-project-1",
"my-service-project-2"
]
}
}

View File

@ -0,0 +1 @@
parent = null

View File

@ -0,0 +1,22 @@
# 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:
google_project.project[0]:
project_id: my-project
folder_id: null
org_id: null
counts:
google_project: 1

View File

@ -0,0 +1 @@
prefix = null

View File

@ -0,0 +1,20 @@
# 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:
google_project.project[0]:
project_id: my-project
counts:
google_project: 1

View File

@ -0,0 +1,53 @@
# 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:
google_org_policy_policy.default["iam.disableServiceAccountKeyCreation"]:
name: projects/my-project/policies/iam.disableServiceAccountKeyCreation
parent: projects/my-project
spec:
- inherit_from_parent: null
reset: null
rules:
- allow_all: null
condition: []
deny_all: null
enforce: 'TRUE'
values: []
timeouts: null
google_org_policy_policy.default["iam.disableServiceAccountKeyUpload"]:
name: projects/my-project/policies/iam.disableServiceAccountKeyUpload
parent: projects/my-project
spec:
- inherit_from_parent: null
reset: null
rules:
- allow_all: null
condition: []
deny_all: null
enforce: 'FALSE'
values: []
- allow_all: null
condition:
- description: test condition
expression: resource.matchTagId(aa, bb)
location: xxx
title: condition
deny_all: null
enforce: 'TRUE'
values: []
timeouts: null
counts:
google_org_policy_policy: 2

View File

@ -3,6 +3,7 @@ org_policies = {
deny = { all = true }
}
"iam.allowedPolicyMemberDomains" = {
inherit_from_parent = true
allow = {
values = ["C0xxxxxxx", "C0yyyyyyy"]
}

View File

@ -0,0 +1,85 @@
# 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:
google_org_policy_policy.default["compute.restrictLoadBalancerCreationForTypes"]:
name: projects/my-project/policies/compute.restrictLoadBalancerCreationForTypes
parent: projects/my-project
spec:
- 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
expression: resource.matchTagId(aa, bb)
location: xxx
title: condition
deny_all: null
enforce: null
values:
- allowed_values:
- EXTERNAL_1
denied_values: null
- allow_all: 'TRUE'
condition:
- description: test condition2
expression: resource.matchTagId(cc, dd)
location: xxx
title: condition2
deny_all: null
enforce: null
values: []
timeouts: null
google_org_policy_policy.default["compute.vmExternalIpAccess"]:
name: projects/my-project/policies/compute.vmExternalIpAccess
parent: projects/my-project
spec:
- inherit_from_parent: null
reset: null
rules:
- allow_all: null
condition: []
deny_all: 'TRUE'
enforce: null
values: []
timeouts: null
google_org_policy_policy.default["iam.allowedPolicyMemberDomains"]:
name: projects/my-project/policies/iam.allowedPolicyMemberDomains
parent: projects/my-project
spec:
- inherit_from_parent: true
reset: null
rules:
- allow_all: null
condition: []
deny_all: null
enforce: null
values:
- allowed_values:
- C0xxxxxxx
- C0yyyyyyy
denied_values: null
timeouts: null
counts:
google_org_policy_policy: 3

View File

@ -0,0 +1 @@
parent = "folders/12345678"

View File

@ -0,0 +1,22 @@
# 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:
google_project.project[0]:
project_id: my-project
folder_id: '12345678'
org_id: null
counts:
google_project: 1

View File

@ -0,0 +1 @@
parent = "organizations/12345678"

View File

@ -0,0 +1,22 @@
# 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:
google_project.project[0]:
project_id: my-project
folder_id: null
org_id: '12345678'
counts:
google_project: 1

View File

@ -0,0 +1 @@
prefix = "foo"

View File

@ -0,0 +1,20 @@
# 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:
google_project.project[0]:
project_id: foo-my-project
counts:
google_project: 1

View File

@ -0,0 +1,4 @@
service_encryption_key_ids = {
compute = ["key1"],
storage = ["key1", "key2"]
}

View File

@ -0,0 +1,44 @@
# 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:
google_kms_crypto_key_iam_member.service_identity_cmek["compute.key1"]:
condition: []
crypto_key_id: key1
role: roles/cloudkms.cryptoKeyEncrypterDecrypter
google_kms_crypto_key_iam_member.service_identity_cmek["storage.key1"]:
condition: []
crypto_key_id: key1
role: roles/cloudkms.cryptoKeyEncrypterDecrypter
google_kms_crypto_key_iam_member.service_identity_cmek["storage.key2"]:
condition: []
crypto_key_id: key2
role: roles/cloudkms.cryptoKeyEncrypterDecrypter
google_project.project[0]:
auto_create_network: false
billing_account: null
folder_id: null
labels: null
name: my-project
org_id: null
project_id: my-project
skip_delete: false
timeouts: null
counts:
google_kms_crypto_key_iam_member: 3
google_project: 1
outputs:
name: my-project

View File

@ -1,58 +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_iam(plan_runner):
"Test IAM bindings."
iam = (
'{"roles/owner" = ["user:one@example.org"],'
'"roles/viewer" = ["user:two@example.org", "user:three@example.org"]}'
)
_, resources = plan_runner(iam=iam)
roles = dict((r['values']['role'], r['values']['members'])
for r in resources if r['type'] == 'google_project_iam_binding')
assert roles == {
'roles/owner': ['user:one@example.org'],
'roles/viewer': ['user:three@example.org', 'user:two@example.org']}
def test_iam_additive(plan_runner):
"Test IAM additive bindings."
iam = (
'{"roles/owner" = ["user:one@example.org"],'
'"roles/viewer" = ["user:two@example.org", "user:three@example.org"]}'
)
_, resources = plan_runner(iam_additive=iam)
roles = set((r['values']['role'], r['values']['member'])
for r in resources if r['type'] == 'google_project_iam_member')
assert roles == set([
('roles/owner', 'user:one@example.org'),
('roles/viewer', 'user:three@example.org'),
('roles/viewer', 'user:two@example.org')
])
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_project_iam_member')
assert roles == set([
('roles/owner', 'user:one@example.org'),
('roles/owner', 'user:two@example.org'),
('roles/editor', 'user:two@example.org')
])

View File

@ -12,65 +12,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
def test_prefix(plan_runner):
"Test project id prefix."
_, resources = plan_runner()
assert len(resources) == 4
[project_resource] = [r for r in resources if r['address'] == 'module.test.google_project.project[0]']
assert project_resource['values']['name'] == 'my-project'
_, resources = plan_runner(prefix='foo')
assert len(resources) == 4
[project_resource] = [r for r in resources if r['address'] == 'module.test.google_project.project[0]']
assert project_resource['values']['name'] == 'foo-my-project'
def test_parent(plan_runner):
"Test project parent."
_, resources = plan_runner(parent='folders/12345678')
assert len(resources) == 4
[project_resource] = [r for r in resources if r['address'] == 'module.test.google_project.project[0]']
assert project_resource['values']['folder_id'] == '12345678'
assert project_resource['values'].get('org_id') == None
_, resources = plan_runner(parent='organizations/12345678')
assert len(resources) == 4
[project_resource] = [r for r in resources if r['address'] == 'module.test.google_project.project[0]']
assert project_resource['values']['org_id'] == '12345678'
assert project_resource['values'].get('folder_id') == None
def test_no_parent(plan_runner):
"Test null project parent."
_, resources = plan_runner()
assert len(resources) == 4
[project_resource] = [r for r in resources if r['address'] == 'module.test.google_project.project[0]']
assert project_resource['values'].get('folder_id') == None
assert project_resource['values'].get('org_id') == None
def test_service_encryption_keys(plan_runner):
"Test service encryption keys with no dependencies."
_, resources = plan_runner(service_encryption_key_ids=(
'{compute=["key1"], storage=["key1", "key2"]}'
))
key_bindings = [
r['index'] for r in resources
if r['type'] == 'google_kms_crypto_key_iam_member'
]
assert len(key_bindings), 3
assert key_bindings == ['compute.key1', 'storage.key1', 'storage.key2']
def test_service_encryption_key_dependencies(plan_runner):
"Test service encryption keys with dependencies."
_, resources = plan_runner(service_encryption_key_ids=(
'{compute=["key1"], dataflow=["key1", "key2"]}'
))
key_bindings = [
r['index'] for r in resources
if r['type'] == 'google_kms_crypto_key_iam_member'
]
assert len(key_bindings), 3
# compute.key1 cannot repeat or we'll get a duplicate key error in for_each
assert key_bindings == [
'compute.key1', 'compute.key2', 'dataflow.key1', 'dataflow.key2'
]
# def test_service_encryption_key_dependencies(plan_runner):
# "Test service encryption keys with dependencies."
# _, resources = plan_runner(service_encryption_key_ids=(
# '{compute=["key1"], dataflow=["key1", "key2"]}'))
# key_bindings = [
# r['index']
# for r in resources
# if r['type'] == 'google_kms_crypto_key_iam_member'
# ]
# assert len(key_bindings), 3
# # compute.key1 cannot repeat or we'll get a duplicate key error in for_each
# assert key_bindings == [
# 'compute.key1', 'compute.key2', 'dataflow.key1', 'dataflow.key2'
# ]

View File

@ -1,126 +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) == 12
resource_types = Counter([r["type"] for r in resources])
assert resource_types == {
"google_logging_project_sink": 4,
"google_bigquery_dataset_iam_member": 1,
"google_project": 1,
"google_project_iam_member": 1,
"google_pubsub_topic_iam_member": 1,
"google_storage_bucket_iam_member": 1,
"google_compute_shared_vpc_host_project": 1,
"google_compute_shared_vpc_service_project": 2
}
sinks = [r for r in resources if r["type"] == "google_logging_project_sink"]
assert sorted([r["index"] for r in sinks]) == [
"debug",
"info",
"notice",
"warning",
]
values = [(
r["index"],
r["values"]["filter"],
r["values"]["destination"],
r["values"]["unique_writer_identity"],
) for r in sinks]
assert sorted(values) == [
(
"debug",
"severity=DEBUG",
"logging.googleapis.com/projects/myproject/locations/global/buckets/mybucket",
True,
),
(
"info",
"severity=INFO",
"bigquery.googleapis.com/projects/myproject/datasets/mydataset",
False,
),
(
"notice",
"severity=NOTICE",
"pubsub.googleapis.com/projects/myproject/topics/mytopic",
True,
),
("warning", "severity=WARNING", "storage.googleapis.com/mybucket", False),
]
bindings = [r for r in resources if "member" in r["type"]]
values = [(r["index"], r["type"], r["values"]["role"]) for r in bindings]
assert sorted(values) == [
("debug", "google_project_iam_member", "roles/logging.bucketWriter"),
("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) == 6
exclusions = [
r for r in resources if r["type"] == "google_logging_project_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"),
]

View File

@ -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/project',
tf_var_files=['common.tfvars', f'org_policies_{policy_type}.tfvars'])
yaml_plan = plan_summary('modules/project', tf_var_files=['common.tfvars'],
org_policies_data_path=f'{tmp_path}')
assert tfvars_plan.values == yaml_plan.values

View File

@ -1,26 +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.
import os
def test_svpc(_plan_runner):
"Test Shared VPC service project attachment."
fixture_path = os.path.join(os.path.dirname(__file__), 'fixture')
plan = _plan_runner(fixture_path=fixture_path, _test_service_project='true')
modules = [m for m in plan.root_module['child_modules']]
resources = [r for r in modules[0]['resources'] if r['address'] == 'module.test.google_compute_shared_vpc_host_project.shared_vpc_host[0]']
assert len(resources) == 1
print(modules[1]['resources'])
resources = [r for r in modules[1]['resources'] if r['address'] == 'module.test-svpc-service[0].google_compute_shared_vpc_service_project.shared_vpc_service[0]']
assert len(resources) == 1

View File

@ -0,0 +1,28 @@
# 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: modules/project
common_tfvars:
- common.tfvars
tests:
prefix:
no_prefix:
parent_folder:
parent_org:
no_parent:
service_encryption_keys:
org_policies_list:
org_policies_boolean:

View File

@ -1,160 +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) == 6
policies = [r for r in resources if r['type'] == 'google_org_policy_policy']
assert len(policies) == 2
assert all(x['values']['parent'] == 'projects/my-project' for x in policies)
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) == 7
policies = [r for r in resources if r['type'] == 'google_org_policy_policy']
assert len(policies) == 3
assert all(x['values']['parent'] == 'projects/my-project' for x in policies)
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': []
}