diff --git a/.gitignore b/.gitignore index f952f00..73e222b 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,4 @@ yarn.lock # tf lock file .terraform.lock.hcl +.terraform.lock diff --git a/examples/scoped_example_with_egress_rule/README.md b/examples/scoped_example_with_egress_rule/README.md index cf8b903..cf97683 100644 --- a/examples/scoped_example_with_egress_rule/README.md +++ b/examples/scoped_example_with_egress_rule/README.md @@ -21,6 +21,7 @@ You may use the following gcloud commands: | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | access\_level\_name | Access level name of the Access Policy. | `string` | `"terraform_members_e"` | no | +| access\_level\_name\_dry\_run | Access level name of the Access Policy in Dry-run mode. | `string` | `"terraform_members_e_dry_run"` | no | | buckets\_names | Buckets Names as list of strings | `list(string)` |
[
"bucket1-e",
"bucket2-e"
]
| no | | buckets\_prefix | Bucket Prefix | `string` | `"test-bucket-e"` | no | | members | An allowed list of members (users, service accounts). The signed-in identity originating the request must be a part of one of the provided members. If not specified, a request may come from any user (logged in/not logged in, etc.). Formats: user:{emailid}, serviceAccount:{emailid} | `list(string)` | n/a | yes | diff --git a/examples/scoped_example_with_egress_rule/main.tf b/examples/scoped_example_with_egress_rule/main.tf index 9c76d34..087748f 100644 --- a/examples/scoped_example_with_egress_rule/main.tf +++ b/examples/scoped_example_with_egress_rule/main.tf @@ -14,6 +14,34 @@ * limitations under the License. */ +locals { + egress_policies_dry_run = [ + { + title = "dry-run" + from = { + sources = { + access_levels = [module.access_level_members_dry_run.name] + }, + identity_type = "ANY_SERVICE_ACCOUNT" + } + to = { + resources = [ + "projects/${var.public_project_ids["number"]}" + ] + operations = { + for service in [ + "cloudresourcemanager.googleapis.com", + "cloudfunctions.googleapis.com", + ] : service => + { + methods = ["*"] + } + } + } + }, + ] +} + module "access_context_manager_policy" { source = "terraform-google-modules/vpc-service-controls/google" version = "~> 7.1" @@ -36,24 +64,41 @@ module "access_level_members" { regions = var.regions } +module "access_level_members_dry_run" { + source = "terraform-google-modules/vpc-service-controls/google//modules/access_level" + version = "~> 7.1" + + description = "Simple Example Access Level dry-run" + policy = module.access_context_manager_policy.policy_id + name = var.access_level_name_dry_run + members = var.members + regions = var.regions +} + + resource "time_sleep" "wait_for_members" { create_duration = "90s" destroy_duration = "90s" - depends_on = [module.access_level_members] + depends_on = [ + module.access_level_members, + module.access_level_members_dry_run + ] } module "regular_service_perimeter_1" { source = "terraform-google-modules/vpc-service-controls/google//modules/regular_service_perimeter" version = "~> 7.1" - policy = module.access_context_manager_policy.policy_id perimeter_name = var.perimeter_name - description = "Perimeter shielding bigquery project" - resources = [var.protected_project_ids["number"]] - access_levels = [module.access_level_members.name] + description = "Perimeter shielding bigquery project" + resources = [var.protected_project_ids["number"]] + resources_dry_run = [var.protected_project_ids["number"]] + access_levels = [module.access_level_members.name] + access_levels_dry_run = [module.access_level_members_dry_run.name] + restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"] @@ -109,6 +154,9 @@ module "regular_service_perimeter_1" { }, ] + egress_policies_dry_run = distinct(tolist(local.egress_policies_dry_run)) + egress_policies_keys_dry_run = ["rule_one"] + shared_resources = { all = [var.protected_project_ids["number"]] } diff --git a/examples/scoped_example_with_egress_rule/variables.tf b/examples/scoped_example_with_egress_rule/variables.tf index 1d8ecc1..bceeab4 100644 --- a/examples/scoped_example_with_egress_rule/variables.tf +++ b/examples/scoped_example_with_egress_rule/variables.tf @@ -57,6 +57,12 @@ variable "access_level_name" { default = "terraform_members_e" } +variable "access_level_name_dry_run" { + description = "Access level name of the Access Policy in Dry-run mode." + type = string + default = "terraform_members_e_dry_run" +} + variable "buckets_prefix" { description = "Bucket Prefix" type = string @@ -74,3 +80,4 @@ variable "scopes" { type = list(string) default = [] } + diff --git a/examples/scoped_example_with_ingress_rule/README.md b/examples/scoped_example_with_ingress_rule/README.md index 0a2f79a..9840d47 100644 --- a/examples/scoped_example_with_ingress_rule/README.md +++ b/examples/scoped_example_with_ingress_rule/README.md @@ -21,6 +21,7 @@ You may use the following gcloud commands: | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | access\_level\_name | Access level name of the Access Policy. | `string` | `"terraform_members"` | no | +| access\_level\_name\_dry\_run | Access level name of the Access Policy in Dry-run mode. | `string` | `"terraform_members_dry_run"` | no | | buckets\_names | Buckets Names as list of strings | `list(string)` |
[
"bucket1",
"bucket2"
]
| no | | buckets\_prefix | Bucket Prefix | `string` | `"test-bucket"` | no | | members | An allowed list of members (users, service accounts). The signed-in identity originating the request must be a part of one of the provided members. If not specified, a request may come from any user (logged in/not logged in, etc.). Formats: user:{emailid}, serviceAccount:{emailid} | `list(string)` | n/a | yes | diff --git a/examples/scoped_example_with_ingress_rule/main.tf b/examples/scoped_example_with_ingress_rule/main.tf index 3272f30..adb8466 100644 --- a/examples/scoped_example_with_ingress_rule/main.tf +++ b/examples/scoped_example_with_ingress_rule/main.tf @@ -14,6 +14,33 @@ * limitations under the License. */ +locals { + ingress_policies_dry_run = [ + { + title = "dry-run" + from = { + identities = var.read_bucket_identities + sources = { + access_levels = [module.access_level_members_dry_run.name] + }, + } + to = { + resources = [ + "*" + ] + operations = { + "storage.googleapis.com" = { + methods = [ + "google.storage.objects.get", + "google.storage.objects.list" + ] + } + } + } + } + ] +} + module "access_context_manager_policy" { source = "terraform-google-modules/vpc-service-controls/google" version = "~> 7.1" @@ -36,11 +63,25 @@ module "access_level_members" { regions = var.regions } +module "access_level_members_dry_run" { + source = "terraform-google-modules/vpc-service-controls/google//modules/access_level" + version = "~> 7.1" + + description = "Simple Example Access Level dry-run" + policy = module.access_context_manager_policy.policy_id + name = var.access_level_name_dry_run + members = var.members + regions = var.regions +} + resource "time_sleep" "wait_for_members" { create_duration = "90s" destroy_duration = "90s" - depends_on = [module.access_level_members] + depends_on = [ + module.access_level_members, + module.access_level_members_dry_run + ] } module "regular_service_perimeter_1" { @@ -50,9 +91,11 @@ module "regular_service_perimeter_1" { policy = module.access_context_manager_policy.policy_id perimeter_name = var.perimeter_name - description = "Perimeter shielding bigquery project" - resources = [var.protected_project_ids["number"]] - access_levels = [module.access_level_members.name] + description = "Perimeter shielding bigquery project" + resources = [var.protected_project_ids["number"]] + resources_dry_run = [var.protected_project_ids["number"]] + access_levels = [module.access_level_members.name] + access_levels_dry_run = [module.access_level_members_dry_run.name] restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"] @@ -60,11 +103,10 @@ module "regular_service_perimeter_1" { { title = "Allow Access from everywhere" from = { + identities = var.read_bucket_identities sources = { access_levels = ["*"] # Allow Access from everywhere }, - identities = var.read_bucket_identities - } to = { resources = [ @@ -80,8 +122,6 @@ module "regular_service_perimeter_1" { } } }, - - { title = "Allow Access from project" from = { @@ -106,9 +146,12 @@ module "regular_service_perimeter_1" { } }, { - title = "without from source" + title = "from bucket read identity" from = { identities = var.read_bucket_identities + sources = { + resources = ["projects/${var.public_project_ids["number"]}"] + } } to = { resources = [ @@ -126,6 +169,10 @@ module "regular_service_perimeter_1" { } ] + ingress_policies_dry_run = distinct(tolist(local.ingress_policies_dry_run)) + ingress_policies_keys_dry_run = ["rule_one"] + + shared_resources = { all = [var.protected_project_ids["number"]] } diff --git a/examples/scoped_example_with_ingress_rule/variables.tf b/examples/scoped_example_with_ingress_rule/variables.tf index 70b6aa5..88b09f3 100644 --- a/examples/scoped_example_with_ingress_rule/variables.tf +++ b/examples/scoped_example_with_ingress_rule/variables.tf @@ -57,6 +57,12 @@ variable "access_level_name" { default = "terraform_members" } +variable "access_level_name_dry_run" { + description = "Access level name of the Access Policy in Dry-run mode." + type = string + default = "terraform_members_dry_run" +} + variable "read_bucket_identities" { description = "List of all identities should get read access on bucket" type = list(string) diff --git a/modules/regular_service_perimeter/README.md b/modules/regular_service_perimeter/README.md index f642fad..c997e49 100644 --- a/modules/regular_service_perimeter/README.md +++ b/modules/regular_service_perimeter/README.md @@ -100,12 +100,16 @@ module "regular_service_perimeter_1" { | description | Description of the regular perimeter | `string` | n/a | yes | | egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress\_from and egress\_to.

Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
title = optional(string, null)
from = object({
sources = optional(object({
resources = optional(list(string), [])
access_levels = optional(list(string), [])
}), {}),
identity_type = optional(string, null)
identities = optional(list(string), null)
})
to = object({
operations = optional(map(object({
methods = optional(list(string), [])
permissions = optional(list(string), [])
})), {}),
roles = optional(list(string), null)
resources = optional(list(string), ["*"])
external_resources = optional(list(string), [])
})
}))
| `[]` | no | | egress\_policies\_dry\_run | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress\_from and egress\_to. Use same formatting as `egress_policies`. |
list(object({
title = optional(string, null)
from = object({
sources = optional(object({
resources = optional(list(string), [])
access_levels = optional(list(string), [])
}), {}),
identity_type = optional(string, null)
identities = optional(list(string), null)
})
to = object({
operations = optional(map(object({
methods = optional(list(string), [])
permissions = optional(list(string), [])
})), {}),
roles = optional(list(string), null)
resources = optional(list(string), ["*"])
external_resources = optional(list(string), [])
})
}))
| `[]` | no | +| egress\_policies\_keys | A list of keys to use for the Terraform state. The order should correspond to var.egress\_policies and the keys must not be dynamically computed. If `null`, var.egress\_policies will be used as keys. | `list(string)` | `null` | no | +| egress\_policies\_keys\_dry\_run | (Dry-run) A list of keys to use for the Terraform state. The order should correspond to var.egress\_policies\_dry\_run and the keys must not be dynamically computed. If `null`, var.egress\_policies\_dry\_run will be used as keys. | `list(string)` | `null` | no | | ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.

Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`

Valid Values:
`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`
`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)
`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) |
list(object({
title = optional(string, null)
from = object({
sources = optional(object({
resources = optional(list(string), [])
access_levels = optional(list(string), [])
}), {}),
identity_type = optional(string, null)
identities = optional(list(string), null)
})
to = object({
operations = optional(map(object({
methods = optional(list(string), [])
permissions = optional(list(string), [])
})), {}),
roles = optional(list(string), null)
resources = optional(list(string), ["*"])
})
}))
| `[]` | no | | ingress\_policies\_dry\_run | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress\_from and ingress\_to. Use same formatting as `ingress_policies`. |
list(object({
title = optional(string, null)
from = object({
sources = optional(object({
resources = optional(list(string), [])
access_levels = optional(list(string), [])
}), {}),
identity_type = optional(string, null)
identities = optional(list(string), null)
})
to = object({
operations = optional(map(object({
methods = optional(list(string), [])
permissions = optional(list(string), [])
})), {}),
roles = optional(list(string), null)
resources = optional(list(string), ["*"])
})
}))
| `[]` | no | +| ingress\_policies\_keys | A list of keys to use for the Terraform state. The order should correspond to var.ingress\_policies and the keys must not be dynamically computed. If `null`, var.ingress\_policies will be used as keys. | `list(string)` | `null` | no | +| ingress\_policies\_keys\_dry\_run | (Dry-run) A list of keys to use for the Terraform state. The order should correspond to var.ingress\_policies\_dry\_run and the keys must not be dynamically computed. If `null`, var.ingress\_policies\_dry\_run will be used as keys. | `list(string)` | `null` | no | | perimeter\_name | Name of the perimeter. Should be one unified string. Must only be letters, numbers and underscores | `string` | n/a | yes | | policy | Name of the parent policy | `string` | n/a | yes | | resource\_keys | A list of keys to use for the Terraform state. The order should correspond to var.resources and the keys must not be dynamically computed. If `null`, var.resources will be used as keys. | `list(string)` | `null` | no | -| resource\_keys\_dry\_run | A list of keys to use for the Terraform state. The order should correspond to var.resources\_dry\_run and the keys must not be dynamically computed. If `null`, var.resources\_dry\_run will be used as keys. | `list(string)` | `null` | no | +| resource\_keys\_dry\_run | (Dry-run) A list of keys to use for the Terraform state. The order should correspond to var.resources\_dry\_run and the keys must not be dynamically computed. If `null`, var.resources\_dry\_run will be used as keys. | `list(string)` | `null` | no | | resources | A list of GCP resources that are inside of the service perimeter. Currently only projects and VPC networks are allowed. | `list(string)` | `[]` | no | | resources\_dry\_run | (Dry-run) A list of GCP resources that are inside of the service perimeter. Currently only projects and VPC networks are allowed. If set, a dry-run policy will be set. | `list(string)` | `[]` | no | | restricted\_services | GCP services that are subject to the Service Perimeter restrictions. Must contain a list of services. For example, if storage.googleapis.com is specified, access to the storage buckets inside the perimeter must meet the perimeter's access restrictions. | `list(string)` | `[]` | no | diff --git a/modules/regular_service_perimeter/main.tf b/modules/regular_service_perimeter/main.tf index ca79038..dd0aa33 100644 --- a/modules/regular_service_perimeter/main.tf +++ b/modules/regular_service_perimeter/main.tf @@ -15,7 +15,7 @@ */ locals { - dry_run = (length(var.restricted_services_dry_run) > 0 || length(var.resources_dry_run) > 0 || length(var.access_levels_dry_run) > 0 || !contains(var.vpc_accessible_services_dry_run, "*")) + dry_run = (length(var.restricted_services_dry_run) > 0 || length(var.resources_dry_run) > 0 || length(var.access_levels_dry_run) > 0 || length(var.egress_policies_dry_run) > 0 || length(var.ingress_policies_dry_run) > 0 || !contains(var.vpc_accessible_services_dry_run, "*")) } resource "google_access_context_manager_service_perimeter" "regular_service_perimeter" { @@ -80,13 +80,14 @@ resource "google_access_context_manager_service_perimeter" "regular_service_peri } locals { + # enforced resource_keys = var.resource_keys != null ? var.resource_keys : var.resources resources = { for rk in local.resource_keys : rk => var.resources[index(local.resource_keys, rk)] } - #dry-run + # dry-run resource_keys_dry_run = var.resource_keys_dry_run != null ? var.resource_keys_dry_run : var.resources_dry_run resources_dry_run = { for rk in local.resource_keys_dry_run : diff --git a/modules/regular_service_perimeter/variables.tf b/modules/regular_service_perimeter/variables.tf index 1ebecb7..a8ed8a1 100644 --- a/modules/regular_service_perimeter/variables.tf +++ b/modules/regular_service_perimeter/variables.tf @@ -66,7 +66,31 @@ variable "resources_dry_run" { } variable "resource_keys_dry_run" { - description = "A list of keys to use for the Terraform state. The order should correspond to var.resources_dry_run and the keys must not be dynamically computed. If `null`, var.resources_dry_run will be used as keys." + description = "(Dry-run) A list of keys to use for the Terraform state. The order should correspond to var.resources_dry_run and the keys must not be dynamically computed. If `null`, var.resources_dry_run will be used as keys." + type = list(string) + default = null +} + +variable "ingress_policies_keys" { + description = "A list of keys to use for the Terraform state. The order should correspond to var.ingress_policies and the keys must not be dynamically computed. If `null`, var.ingress_policies will be used as keys." + type = list(string) + default = null +} + +variable "egress_policies_keys" { + description = "A list of keys to use for the Terraform state. The order should correspond to var.egress_policies and the keys must not be dynamically computed. If `null`, var.egress_policies will be used as keys." + type = list(string) + default = null +} + +variable "ingress_policies_keys_dry_run" { + description = "(Dry-run) A list of keys to use for the Terraform state. The order should correspond to var.ingress_policies_dry_run and the keys must not be dynamically computed. If `null`, var.ingress_policies_dry_run will be used as keys." + type = list(string) + default = null +} + +variable "egress_policies_keys_dry_run" { + description = "(Dry-run) A list of keys to use for the Terraform state. The order should correspond to var.egress_policies_dry_run and the keys must not be dynamically computed. If `null`, var.egress_policies_dry_run will be used as keys." type = list(string) default = null } diff --git a/modules/regular_service_perimeter/vpc-sc-policies.tf b/modules/regular_service_perimeter/vpc-sc-policies.tf index f062e3e..4937620 100644 --- a/modules/regular_service_perimeter/vpc-sc-policies.tf +++ b/modules/regular_service_perimeter/vpc-sc-policies.tf @@ -14,8 +14,42 @@ * limitations under the License. */ + + +locals { + # enforced + # ingress_rules + ingress_policies_keys = var.ingress_policies_keys != null ? var.ingress_policies_keys : [for k, v in var.ingress_policies : tostring(k)] + ingress_policies = { + for ipk in local.ingress_policies_keys : + ipk => var.ingress_policies[index(local.ingress_policies_keys, ipk)] + } + + # egress_rules + egress_policies_keys = var.egress_policies_keys != null ? var.egress_policies_keys : [for k, v in var.egress_policies : tostring(k)] + egress_policies = { + for epk in local.egress_policies_keys : + epk => var.egress_policies[index(local.egress_policies_keys, epk)] + } + + # dry-run + # ingress_rules + ingress_policies_keys_dry_run = var.ingress_policies_keys_dry_run != null ? var.ingress_policies_keys_dry_run : [for k, v in var.ingress_policies_dry_run : tostring(k)] + ingress_policies_dry_run = { + for ipk in local.ingress_policies_keys_dry_run : + ipk => var.ingress_policies_dry_run[index(local.ingress_policies_keys_dry_run, ipk)] + } + + # egress_rules + egress_policies_keys_dry_run = var.egress_policies_keys_dry_run != null ? var.egress_policies_keys_dry_run : [for k, v in var.egress_policies_dry_run : tostring(k)] + egress_policies_dry_run = { + for epk in local.egress_policies_keys_dry_run : + epk => var.egress_policies_dry_run[index(local.egress_policies_keys_dry_run, epk)] + } +} + resource "google_access_context_manager_service_perimeter_ingress_policy" "ingress_policies" { - for_each = { for k, v in var.ingress_policies : k => v } + for_each = local.ingress_policies perimeter = google_access_context_manager_service_perimeter.regular_service_perimeter.name title = coalesce(each.value["title"], "Ingress Policy ${each.key}") @@ -59,7 +93,7 @@ resource "google_access_context_manager_service_perimeter_ingress_policy" "ingre } resource "google_access_context_manager_service_perimeter_egress_policy" "egress_policies" { - for_each = { for k, v in var.egress_policies : k => v } + for_each = local.egress_policies perimeter = google_access_context_manager_service_perimeter.regular_service_perimeter.name title = coalesce(each.value["title"], "Egress Policy ${each.key}") @@ -109,7 +143,7 @@ resource "google_access_context_manager_service_perimeter_egress_policy" "egress ############################################ resource "google_access_context_manager_service_perimeter_dry_run_ingress_policy" "ingress_policies" { - for_each = { for k, v in var.ingress_policies_dry_run : k => v } + for_each = local.ingress_policies_dry_run perimeter = google_access_context_manager_service_perimeter.regular_service_perimeter.name title = coalesce(each.value["title"], "Ingress Policy ${each.key}") @@ -153,7 +187,7 @@ resource "google_access_context_manager_service_perimeter_dry_run_ingress_policy } resource "google_access_context_manager_service_perimeter_dry_run_egress_policy" "egress_policies" { - for_each = { for k, v in var.egress_policies_dry_run : k => v } + for_each = local.egress_policies_dry_run perimeter = google_access_context_manager_service_perimeter.regular_service_perimeter.name title = coalesce(each.value["title"], "Egress Policy ${each.key}") diff --git a/test/integration/scoped_example_with_egress_rule/scoped_example_with_egress_rule_test.go b/test/integration/scoped_example_with_egress_rule/scoped_example_with_egress_rule_test.go index 720a22c..67e483a 100644 --- a/test/integration/scoped_example_with_egress_rule/scoped_example_with_egress_rule_test.go +++ b/test/integration/scoped_example_with_egress_rule/scoped_example_with_egress_rule_test.go @@ -60,6 +60,11 @@ func TestScopedExampleWithEgressRule(t *testing.T) { "google.storage.objects.list", } + dryRunServices := []string{ + "cloudfunctions.googleapis.com", + "cloudresourcemanager.googleapis.com", + } + setup := tft.NewTFBlueprintTest(t, tft.WithTFDir("../../setup"), ) @@ -80,6 +85,21 @@ func TestScopedExampleWithEgressRule(t *testing.T) { servicePerimeterLink := fmt.Sprintf("accessPolicies/%s/servicePerimeters/%s", policyID, bpt.GetStringOutput("service_perimeter_name")) servicePerimeter := gcloud.Runf(t, "access-context-manager perimeters describe %s --policy %s", servicePerimeterLink, policyID) + egressPoliciesDryRun := servicePerimeter.Get("spec.egressPolicies").Array() + for _, ruleDryRun := range egressPoliciesDryRun { + from := ruleDryRun.Get("egressFrom") + assert.Equal("ANY_SERVICE_ACCOUNT", from.Get("identityType").String(), "identityType should be ANY_SERVICE_ACCOUNT") + assert.Equal("SOURCE_RESTRICTION_ENABLED", from.Get("sourceRestriction").String(), "source restriction should be enabled") + assert.Equal(fmt.Sprintf("accessPolicies/%s/accessLevels/terraform_members_e_dry_run", policyID), from.Get("sources").Array()[0].Get("accessLevel").String(), "source accessLevel should be terraform_members_e_dry_run") + + to := ruleDryRun.Get("egressTo") + resource := to.Get("resources").Array()[0] + assert.Equal(fmt.Sprintf("projects/%s", publicProjectNumber), resource.String(), "to public project should be %s", publicProjectNumber) + operation := to.Get("operations").Array()[0] + assert.Contains(dryRunServices, operation.Get("serviceName").String()) + assert.Equal("*",operation.Get("methodSelectors").Array()[0].Get("method").String()) + } + egressPolicies := servicePerimeter.Get("status.egressPolicies").Array() for _, rule := range egressPolicies { diff --git a/test/integration/scoped_example_with_ingress_rule/scoped_example_with_ingress_rule_test.go b/test/integration/scoped_example_with_ingress_rule/scoped_example_with_ingress_rule_test.go index b39f5aa..32d6f49 100644 --- a/test/integration/scoped_example_with_ingress_rule/scoped_example_with_ingress_rule_test.go +++ b/test/integration/scoped_example_with_ingress_rule/scoped_example_with_ingress_rule_test.go @@ -71,6 +71,24 @@ func TestScopedExampleWithIngressRule(t *testing.T) { servicePerimeterLink := fmt.Sprintf("accessPolicies/%s/servicePerimeters/%s", policyID, bpt.GetStringOutput("service_perimeter_name")) servicePerimeter := gcloud.Runf(t, "access-context-manager perimeters describe %s --policy %s", servicePerimeterLink, policyID) + ingressPoliciesDryRun := servicePerimeter.Get("spec.ingressPolicies").Array() + for _, ruleDryRun := range ingressPoliciesDryRun { + + from := ruleDryRun.Get("ingressFrom") + assert.NotEmpty(from.Get("identities").Array()) + assert.Equal(fmt.Sprintf("accessPolicies/%s/accessLevels/terraform_members_dry_run", policyID), from.Get("sources").Array()[0].Get("accessLevel").String(), "accessLevel should be 'terraform_members_dry_run'") + + to := ruleDryRun.Get("ingressTo") + operation := to.Get("operations").Array()[0] + assert.Equal("storage.googleapis.com", operation.Get("serviceName").String(), "service should be storage.googleapis.com") + methods := GetResultFieldStrSlice(operation.Get("methodSelectors").Array(), "method") + for _, expected := range expectedMethods { + assert.Contains(methods, expected) + } + resource := to.Get("resources").Array()[0] + assert.Equal("*", resource.String(), "should be all projects *") + } + ingressPolicies := servicePerimeter.Get("status.ingressPolicies").Array() for _, rule := range ingressPolicies { @@ -79,8 +97,9 @@ func TestScopedExampleWithIngressRule(t *testing.T) { if rule.Get("title").String() == "Allow Access from everywhere" { assert.Equal("*", from.Get("sources").Array()[0].Get("accessLevel").String(), "accessLevel should be '*'") } - if rule.Get("title").String() == "without from source" { + if rule.Get("title").String() == "from bucket read identity" { assert.NotEmpty(from.Get("identities").Array()) + assert.Equal(fmt.Sprintf("projects/%s", publicProjectNumber), from.Get("sources").Array()[0].Get("resource").String(), "source project should be %s", publicProjectNumber) } if rule.Get("title").String() == "Allow Access from project" { assert.Equal("ANY_SERVICE_ACCOUNT", from.Get("identityType").String(), "identityType should be ANY_SERVICE_ACCOUNT") @@ -99,7 +118,7 @@ func TestScopedExampleWithIngressRule(t *testing.T) { if rule.Get("title").String() == "Allow Access from everywhere" { assert.Equal("*", resource.String(), "should be all projects '*'") } - if rule.Get("title").String() == "without from source" { + if rule.Get("title").String() == "from bucket read identity" { assert.Equal(fmt.Sprintf("projects/%s", protectedProjectNumber), resource.String(), "to protected project should be %s", protectedProjectNumber) } if rule.Get("title").String() == "Allow Access from project" {