Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

To create a VPC SC access policy and access perimeter

I'm working on a usecase to create an access policy on the 'org' level. Through terraform module google_access_context_manager_access_policy. While deploying a terraform configuration, got this exception as ,

Error: Error creating AccessPolicy: googleapi: Error 403: Your application is authenticating by using local Application Default Credentials. The accesscontextmanager.googleapis.com API requires a quota project, which is not set by default. To learn how to set your quota project, see https://cloud.google.com/docs/authentication/adc-troubleshooting/user-creds .
│ Details:
│ [
│   {
│     "@type": "type.googleapis.com/google.rpc.ErrorInfo",
│     "domain": "googleapis.com",
│     "metadata": {
│       "consumer": "projects/6034567846021",
│       "service": "accesscontextmanager.googleapis.com"
│     },
│     "reason": "SERVICE_DISABLED"
│   }
│ ] 

reference: https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/access_context_manage...

Any references or suggestions to overcome this error? To create an access policy and the access perimeter on the "org" level.

 

3 5 658
5 REPLIES 5

Hi @Dg03cloud,

It looks like the error you're encountering indicate that the Google Cloud service is not yet enabled on your project or no quota project being set.
Make sure you enable Access Context Manager API on your Google project.

You can enable the API by using this command on your Google Shell:

glcoud services enable accesscontextmanager.googleapis.com

 Update the ADC 

gcloud auth application-default set-quota-project YOUR_PROJECT

Double check your credentials in your Terraform configuration, IAM permissions before proceeding.

Let me know if this helps you. 

I’m able to enable necessary APIs, and above error is fine now. What is the best practice to create an access perimeter with a dry run mode through terraform. Any helpful references on this scenario?

Good day @Dg03cloud ,

There are some documentations I've found in Terraform's website that might be helpful on your use case however you might also want to check first the GCP documentation on dry run mode for service perimeters as it can guide you on your implementation.

Hope this helps you! 

@Rfelizardo Appreciate your reply. I'm trying to create a gcp access context manager access policy and then to create a regular service perimeter in a "dry_run" mode on the organization level through a terraform module. I'm referring to the below terraform registry to provision these resources. I'm able to create an access policy on the organization level without any issue.

Following this terraform module reference:- https://github.com/terraform-google-modules/terraform-google-vpc-service-controls/blob/v6.0.0/module...

Terraform configuration:- 

Child module -> main.tf:-

module "regular_service_perimeter_1" {
source = "terraform-google-modules/vpc-service-controls/google//modules/regular_service_perimeter"
policy = "google_access_context_manager_access_policy.org.id"
perimeter_name = "abc-hgt-fg0e-perimeter1"
description = "abc com access perimeter"
resources = ["abc-test-pro-d1, abc-test-pro-d1-75b2"]
use_explicit_dry_run_spec = true
restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"]
shared_resources = {
all = ["abc-test-pro-d1, abc-test-pro-d1-75b2"]
}
}

Root module -> main.tf

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, "*"))
}

resource "google_access_context_manager_service_perimeter" "regular_service_perimeter" {
provider = google
parent = "accessPolicies/${var.policy}"
perimeter_type = "PERIMETER_TYPE_REGULAR"
name = "accessPolicies/${var.policy}/servicePerimeters/${var.perimeter_name}"
title = var.perimeter_name
description = var.description

status {
restricted_services = var.restricted_services
access_levels = formatlist(
"accessPolicies/${var.policy}/accessLevels/%s",
var.access_levels
)

dynamic "ingress_policies" {
for_each = var.ingress_policies
iterator = ingress_policies
content {
ingress_from {
dynamic "sources" {
for_each = merge(
{ for k, v in lookup(ingress_policies.value["from"]["sources"], "resources", []) : v => "resource" },
{ for k, v in lookup(ingress_policies.value["from"]["sources"], "access_levels", []) : v => "access_level" })
content {
resource = sources.value == "resource" ? sources.key : null
access_level = sources.value == "access_level" ? sources.key != "*" ? "accessPolicies/${var.policy}/accessLevels/${sources.key}" : "*" : null
}
}
identity_type = lookup(ingress_policies.value["from"], "identity_type", null)
identities = lookup(ingress_policies.value["from"], "identities", null)
}

ingress_to {
resources = lookup(ingress_policies.value["to"], "resources", ["*"])
dynamic "operations" {
for_each = ingress_policies.value["to"]["operations"]
content {
service_name = operations.key
dynamic "method_selectors" {
for_each = operations.key != "*" ? merge(
{ for v in lookup(operations.value, "methods", []) : v => "method" },
{ for v in lookup(operations.value, "permissions", []) : v => "permission" }) : {}
content {
method = method_selectors.value == "method" ? method_selectors.key : null
permission = method_selectors.value == "permission" ? method_selectors.key : null
}
}
}
}
}
}
}
dynamic "egress_policies" {
for_each = var.egress_policies
iterator = egress_policies
content {
egress_from {
identity_type = lookup(egress_policies.value["from"], "identity_type", null)
identities = lookup(egress_policies.value["from"], "identities", null)
dynamic "sources" {
for_each = { for k, v in lookup(egress_policies.value["from"]["sources"], "access_levels", []) : v => "access_level" }
content {
access_level = sources.value == "access_level" ? sources.key != "*" ? "accessPolicies/${var.policy}/accessLevels/${sources.key}" : "*" : null
}
}
source_restriction = egress_policies.value["from"]["sources"] != null ? "SOURCE_RESTRICTION_ENABLED" : null
}
egress_to {
resources = lookup(egress_policies.value["to"], "resources", ["*"])
dynamic "operations" {
for_each = lookup(egress_policies.value["to"], "operations", [])
content {
service_name = operations.key
dynamic "method_selectors" {
for_each = operations.key != "*" ? merge(
{ for v in lookup(operations.value, "methods", []) : v => "method" },
{ for v in lookup(operations.value, "permissions", []) : v => "permission" }) : {}
content {
method = method_selectors.value == "method" ? method_selectors.key : null
permission = method_selectors.value == "permission" ? method_selectors.key : null
}
}
}
}
}
}
}

dynamic "vpc_accessible_services" {
for_each = contains(var.vpc_accessible_services, "*") ? [] : [var.vpc_accessible_services]
content {
enable_restriction = true
allowed_services = vpc_accessible_services.value
}
}
}


dynamic "spec" {
for_each = local.dry_run ? ["dry-run"] : []
content {
restricted_services = var.restricted_services_dry_run
resources = [for item in var.resources_dry_run : can(regex("global/networks", item)) ? format("//compute.googleapis.com/%s", item) : format("projects/%s", item)]
access_levels = formatlist(
"accessPolicies/${var.policy}/accessLevels/%s",
var.access_levels_dry_run
)

dynamic "ingress_policies" {
for_each = var.ingress_policies_dry_run
iterator = ingress_policies_dry_run
content {
ingress_from {
dynamic "sources" {
for_each = merge(
{ for k, v in lookup(ingress_policies_dry_run.value["from"]["sources"], "resources", []) : v => "resource" },
{ for k, v in lookup(ingress_policies_dry_run.value["from"]["sources"], "access_levels", []) : v => "access_level" })
content {
resource = sources.value == "resource" ? sources.key : null
access_level = sources.value == "access_level" ? sources.key != "*" ? "accessPolicies/${var.policy}/accessLevels/${sources.key}" : "*" : null
}
}
identity_type = lookup(ingress_policies_dry_run.value["from"], "identity_type", null)
identities = lookup(ingress_policies_dry_run.value["from"], "identities", null)
}

ingress_to {
resources = lookup(ingress_policies_dry_run.value["to"], "resources", ["*"])
dynamic "operations" {
for_each = ingress_policies_dry_run.value["to"]["operations"]
content {
service_name = operations.key
dynamic "method_selectors" {
for_each = operations.key != "*" ? merge(
{ for v in lookup(operations.value, "methods", []) : v => "method" },
{ for v in lookup(operations.value, "permissions", []) : v => "permission" }) : {}
content {
method = method_selectors.value == "method" ? method_selectors.key : null
permission = method_selectors.value == "permission" ? method_selectors.key : null
}
}
}
}
}
}
}
dynamic "egress_policies" {
for_each = var.egress_policies_dry_run
iterator = egress_policies_dry_run
content {
egress_from {
identity_type = lookup(egress_policies_dry_run.value["from"], "identity_type", null)
identities = lookup(egress_policies_dry_run.value["from"], "identities", null)
dynamic "sources" {
for_each = { for k, v in lookup(egress_policies_dry_run.value["from"]["sources"], "access_levels", []) : v => "access_level" }
content {
access_level = sources.value == "access_level" ? sources.key != "*" ? "accessPolicies/${var.policy}/accessLevels/${sources.key}" : "*" : null
}
}
source_restriction = egress_policies_dry_run.value["from"]["sources"] != null ? "SOURCE_RESTRICTION_ENABLED" : null
}
egress_to {
resources = lookup(egress_policies_dry_run.value["to"], "resources", ["*"])
dynamic "operations" {
for_each = lookup(egress_policies_dry_run.value["to"], "operations", [])
content {
service_name = operations.key
dynamic "method_selectors" {
for_each = operations.key != "*" ? merge(
{ for v in lookup(operations.value, "methods", []) : v => "method" },
{ for v in lookup(operations.value, "permissions", []) : v => "permission" }) : {}
content {
method = method_selectors.value == "method" ? method_selectors.key : null
permission = method_selectors.value == "permission" ? method_selectors.key : null
}
}
}
}
}
}
}

dynamic "vpc_accessible_services" {
for_each = contains(var.vpc_accessible_services_dry_run, "*") ? [] : [var.vpc_accessible_services_dry_run]
content {
enable_restriction = true
allowed_services = vpc_accessible_services.value
}
}
}
}
use_explicit_dry_run_spec = local.dry_run

lifecycle {
ignore_changes = [status[0].resources]
}
}

locals {
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)]
}
}

resource "google_access_context_manager_service_perimeter_resource" "service_perimeter_resource" {
for_each = local.resources
perimeter_name = google_access_context_manager_service_perimeter.regular_service_perimeter.name
resource = can(regex("global/networks", each.value)) ? "//compute.googleapis.com/${each.value}" : "projects/${each.value}"
}

To provision a gcp regular service perimeter in a Dry Run mode. Any helpful suggestion to overcome this issue? 

 

 

Error got resolved for above usecase. Thanks!

Top Solution Authors