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"
│ }
│ ]
Any references or suggestions to overcome this error? To create an access policy and the access perimeter on the "org" level.
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!