Skip to content

fix: Directional rules after apply #210

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ yarn.lock

# tf lock file
.terraform.lock.hcl
.terraform.lock
1 change: 1 addition & 0 deletions examples/scoped_example_with_egress_rule/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)` | <pre>[<br> "bucket1-e",<br> "bucket2-e"<br>]</pre> | 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 |
Expand Down
58 changes: 53 additions & 5 deletions examples/scoped_example_with_egress_rule/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"]

Expand Down Expand Up @@ -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"]]
}
Expand Down
7 changes: 7 additions & 0 deletions examples/scoped_example_with_egress_rule/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -74,3 +80,4 @@ variable "scopes" {
type = list(string)
default = []
}

1 change: 1 addition & 0 deletions examples/scoped_example_with_ingress_rule/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)` | <pre>[<br> "bucket1",<br> "bucket2"<br>]</pre> | 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 |
Expand Down
65 changes: 56 additions & 9 deletions examples/scoped_example_with_ingress_rule/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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" {
Expand All @@ -50,21 +91,22 @@ 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"]

ingress_policies = [
{
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 = [
Expand All @@ -80,8 +122,6 @@ module "regular_service_perimeter_1" {
}
}
},


{
title = "Allow Access from project"
from = {
Expand All @@ -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 = [
Expand All @@ -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"]]
}
Expand Down
6 changes: 6 additions & 0 deletions examples/scoped_example_with_ingress_rule/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 5 additions & 1 deletion modules/regular_service_perimeter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.<br><br>Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`<br><br>Valid Values:<br>`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`<br>`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)<br>`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) | <pre>list(object({<br> title = optional(string, null)<br> from = object({<br> sources = optional(object({<br> resources = optional(list(string), [])<br> access_levels = optional(list(string), [])<br> }), {}),<br> identity_type = optional(string, null)<br> identities = optional(list(string), null)<br> })<br> to = object({<br> operations = optional(map(object({<br> methods = optional(list(string), [])<br> permissions = optional(list(string), [])<br> })), {}),<br> roles = optional(list(string), null)<br> resources = optional(list(string), ["*"])<br> external_resources = optional(list(string), [])<br> })<br> }))</pre> | `[]` | 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`. | <pre>list(object({<br> title = optional(string, null)<br> from = object({<br> sources = optional(object({<br> resources = optional(list(string), [])<br> access_levels = optional(list(string), [])<br> }), {}),<br> identity_type = optional(string, null)<br> identities = optional(list(string), null)<br> })<br> to = object({<br> operations = optional(map(object({<br> methods = optional(list(string), [])<br> permissions = optional(list(string), [])<br> })), {}),<br> roles = optional(list(string), null)<br> resources = optional(list(string), ["*"])<br> external_resources = optional(list(string), [])<br> })<br> }))</pre> | `[]` | 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.<br><br>Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`<br><br>Valid Values:<br>`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`<br>`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)<br>`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) | <pre>list(object({<br> title = optional(string, null)<br> from = object({<br> sources = optional(object({<br> resources = optional(list(string), [])<br> access_levels = optional(list(string), [])<br> }), {}),<br> identity_type = optional(string, null)<br> identities = optional(list(string), null)<br> })<br> to = object({<br> operations = optional(map(object({<br> methods = optional(list(string), [])<br> permissions = optional(list(string), [])<br> })), {}),<br> roles = optional(list(string), null)<br> resources = optional(list(string), ["*"])<br> })<br> }))</pre> | `[]` | 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`. | <pre>list(object({<br> title = optional(string, null)<br> from = object({<br> sources = optional(object({<br> resources = optional(list(string), [])<br> access_levels = optional(list(string), [])<br> }), {}),<br> identity_type = optional(string, null)<br> identities = optional(list(string), null)<br> })<br> to = object({<br> operations = optional(map(object({<br> methods = optional(list(string), [])<br> permissions = optional(list(string), [])<br> })), {}),<br> roles = optional(list(string), null)<br> resources = optional(list(string), ["*"])<br> })<br> }))</pre> | `[]` | 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 |
Expand Down
5 changes: 3 additions & 2 deletions modules/regular_service_perimeter/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down Expand Up @@ -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 :
Expand Down
26 changes: 25 additions & 1 deletion modules/regular_service_perimeter/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
Loading