Git Product home page Git Product logo

terraform-google-iam's Introduction

Google IAM Terraform Module

This is a collection of submodules that make it easier to non-destructively manage multiple IAM roles for resources on Google Cloud Platform:

Compatibility

This module is meant for use with Terraform 0.13+ and tested using Terraform 1.0+. If you find incompatibilities using Terraform >=0.13, please open an issue. If you haven't upgraded and need a Terraform 0.12.x-compatible version of this module, the last released version intended for Terraform 0.12.x is v6.4.1.

Upgrading

The following guides are available to assist with upgrades:

Usage

Full examples are in the examples folder, but basic usage is as follows for managing roles on two projects:

module "projects_iam_bindings" {
  source  = "terraform-google-modules/iam/google//modules/projects_iam"
  version = "~> 7.7"

  projects = ["project-123456", "project-9876543"]

  bindings = {
    "roles/storage.admin" = [
      "group:[email protected]",
      "user:[email protected]",
    ]

    "roles/compute.networkAdmin" = [
      "group:[email protected]",
      "user:[email protected]",
    ]

    "roles/compute.imageUser" = [
      "user:[email protected]",
    ]
  }
}

The module also offers an authoritative mode which will remove all roles not assigned through Terraform. This is an example of using the authoritative mode to manage access to a storage bucket:

module "storage_buckets_iam_bindings" {
  source  = "terraform-google-modules/iam/google//modules/storage_buckets_iam"
  version = "~> 8.0"

  storage_buckets = ["my-storage-bucket"]

  mode = "authoritative"

  bindings = {
    "roles/storage.legacyBucketReader" = [
      "user:[email protected]",
      "group:[email protected]",
    ]

    "roles/storage.legacyBucketWriter" = [
      "user:[email protected]",
      "group:[email protected]",
    ]
  }
}

Additive and Authoritative Modes

The mode variable controls a submodule's behavior, by default it's set to "additive", possible options are:

  • additive: add members to role, old members are not deleted from this role.
  • authoritative: set the role's members (including removing any not listed), unlisted roles are not affected.

In authoritative mode, a submodule takes full control over the IAM bindings listed in the module. This means that any members added to roles outside the module will be removed the next time Terraform runs. However, roles not listed in the module will be unaffected.

In additive mode, a submodule leaves existing bindings unaffected. Instead, any members listed in the module will be added to the existing set of IAM bindings. However, members listed in the module are fully controlled by the module. This means that if you add a binding via the module and later remove it, the module will correctly handle removing the role binding.

Caveats

Referencing values/attributes from other resources

Each submodule performs operations over some variables before making any changes on the IAM bindings in GCP. Because of the limitations of for_each (more info), which is widely used in the submodules, there are certain limitations to what kind of dynamic values you can provide to a submodule:

  1. Dynamic entities (for example projects) are only allowed for 1 entity.
  2. If you pass 2 or more entities (for example projects), the configuration MUST be static, meaning that it can't use any of the other resources' fields to get the entity name from (this includes getting the randomly generated hashes through the random_id resource).
  3. The role names themselves can never be dynamic.
  4. Members may only be dynamic in authoritative mode.

IAM Bindings

You can choose the following resource types to apply the IAM bindings:

  • Projects (projects variable)
  • Organizations(organizations variable)
  • Folders (folders variable)
  • Service Accounts (service_accounts variable)
  • Subnetworks (subnets variable)
  • Storage buckets (storage_buckets variable)
  • Pubsub topics (pubsub_topics variable)
  • Pubsub subscriptions (pubsub_subscriptions variable)
  • Kms Key Rings (kms_key_rings variable)
  • Kms Crypto Keys (kms_crypto_keys variable)
  • Secret Manager Secrets (secrets variable)
  • DNS Zones (managed_zones variable)

Set the specified variable on the module call to choose the resources to affect. Remember to set the mode variable and give enough permissions to manage the selected resource as well. Note that the bindings variable accepts an empty map {} passed in as an argument in the case that resources don't have IAM bindings to apply.

Requirements

Terraform plugins

Permissions

In order to execute a submodule you must have a Service Account with an appropriate role to manage IAM for the applicable resource. The appropriate role differs depending on which resource you are targeting, as follows:

  • Organization:
    • Organization Administrator: Access to administer all resources belonging to the organization and does not include privileges for billing or organization role administration.
    • Custom: Add resourcemanager.organizations.getIamPolicy and resourcemanager.organizations.setIamPolicy permissions.
  • Project:
    • Owner: Full access and all permissions for all resources of the project.
    • Projects IAM Admin: allows users to administer IAM policies on projects.
    • Custom: Add resourcemanager.projects.getIamPolicy and resourcemanager.projects.setIamPolicy permissions.
  • Folder:
    • The Folder Admin: All available folder permissions.
    • Folder IAM Admin: Allows users to administer IAM policies on folders.
    • Custom: Add resourcemanager.folders.getIamPolicy and resourcemanager.folders.setIamPolicy permissions (must be added in the organization).
  • Service Account:
    • Service Account Admin: Create and manage service accounts.
    • Custom: Add resourcemanager.organizations.getIamPolicy and resourcemanager.organizations.setIamPolicy permissions.
  • Subnetwork:
    • Project compute admin: Full control of Compute Engine resources.
    • Project compute network admin: Full control of Compute Engine networking resources.
    • Project custom: Add compute.subnetworks.getIamPolicy and compute.subnetworks.setIamPolicy permissions.
  • Storage bucket:
    • Storage Admin: Full control of GCS resources.
    • Storage Legacy Bucket Owner: Read and write access to existing buckets with object listing/creation/deletion.
    • Custom: Add storage.buckets.getIamPolicy and storage.buckets.setIamPolicy permissions.
  • Pubsub topic:
    • Pub/Sub Admin: Create and manage service accounts.
    • Custom: Add pubsub.topics.getIamPolicy and pubsub.topics.setIamPolicy permissions.
  • Pubsub subscription:
    • Pub/Sub Admin role: Create and manage service accounts.
    • Custom role: Add pubsub.subscriptions.getIamPolicy and pubsub.subscriptions.setIamPolicy permissions.
  • Kms Key Ring:
    • Owner: Full access to all resources.
    • Cloud KMS Admin: Enables management of crypto resources.
    • Custom: Add cloudkms.keyRings.getIamPolicy and cloudkms.keyRings.getIamPolicy permissions.
  • Kms Crypto Key:
    • Owner: Full access to all resources.
    • Cloud KMS Admin: Enables management of cryptoresources.
    • Custom: Add cloudkms.cryptoKeys.getIamPolicy and cloudkms.cryptoKeys.setIamPolicy permissions.
  • Secret Manager:
    • Secret Manager Admin: Full access to administer Secret Manager.
    • Custom: Add secretmanager.secrets.getIamPolicy and secretmanager.secrets.setIamPolicy permissions.
  • DNS Zone:
    • DNS Administrator : Full access to administer DNS Zone.
    • Custom: Add dns.managedZones.setIamPolicy, dns.managedZones.list and dns.managedZones.getIamPolicy permissions.

Install

Terraform

Be sure you have the correct Terraform version (0.12), you can choose the binary here:

Terraform plugins

Be sure you have the compiled plugins on $HOME/.terraform.d/plugins/

See each plugin page for more information about how to compile and use them.

Fast install (optional)

For a fast install, please configure the variables on init_centos.sh or init_debian.sh script and then launch it.

The script will do:

  • Environment variables setting
  • Installation of base packages like wget, curl, unzip, gcloud, etc.
  • Installation of go 1.9.0
  • Installation of Terraform 0.10.x
  • Download the terraform-provider-google plugin
  • Compile the terraform-provider-google plugin
  • Move the terraform-provider-google to the right location

terraform-google-iam's People

Contributors

aaron-lane avatar agnnn avatar alexkonkin avatar averbuks avatar bestefreund avatar bharathkkb avatar cloud-foundation-bot avatar cray0000 avatar dependabot[bot] avatar g-awmalik avatar imrannayer avatar ingwarr avatar jberlinsky avatar jeffmccune avatar kenthua avatar kkurnala18 avatar kunalkg11 avatar miguelangelmorenochacon avatar mmckane avatar morgante avatar nstogner avatar omazin avatar paulpalamarchuk avatar r4hulgupta avatar release-please[bot] avatar renovate[bot] avatar ruanda avatar t-v avatar taylorludwig avatar veggiemonk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

terraform-google-iam's Issues

Documentation and examples update for v3.0.0

According to 2.0->3.0 documentation, this should work:

module "owners" {
  source      = "[email protected]:terraform-google-modules/terraform-google-iam.git?ref=v3.0.0"
  folders_mode  = "additive"
  folders     = [substr(data.terraform_remote_state.folders.outputs.folder_id, length("folders/"), -1)]
  folders_bindings  = {
    "roles/owner" = var.owners
  }
}

However i actually had to do:

module "owners" {
  source      = "[email protected]:terraform-google-modules/terraform-google-iam.git?ref=v3.0.0"
  folders_mode  = "additive"
  folders     = [substr(data.terraform_remote_state.folders.outputs.folder_id, length("folders/"), -1)]
  folders_bindings  = {
    "roles/owner" = var.owners
  }
  pubsub_topics_bindings = {}
  pubsub_subscriptions_bindings = {}
  storage_buckets_bindings = {}
  subnets_bindings = {}
  subnets_region = ""
  organizations_bindings = {}
  kms_crypto_keys_bindings = {}
  kms_key_rings_bindings = {}
  service_accounts_bindings = {}
  projects_bindings = {}
}

If required variables are not set the module will not work.

Invalid for_each argument when trying to create additive bindings

Overview

If you try to create a project, service account, and service account binding at the same time, terraform errors out if the binding mode is additive but not if the binding mode is authoritative.

My suspicion is that this is because authoritative uses known values for the keys in the for_each but additive uses the member in the keys, which includes the service account's email and is not known until the service account has been created. If the helper could be refactored so that an unknown value (member) is not in the keys, I suspect additive would no longer cause this error.

Sample Configuration

resource "google_project" "main" {
  name                = var.project_id
  project_id          = var.project_id
  org_id              = var.org_id
  folder_id           = var.folder_id
  billing_account     = var.billing_account
  auto_create_network = false
}

module "google_test_sa" {
  source       = "[email protected]:terraform-google-modules/terraform-google-service-accounts"
  project_id   = google_project.main.project_id
  names        = ["google-test-sa"]
  display_name = "google-test-sa"
}

module "impersonate_service_account_iam_bindings" {
  source = "[email protected]:terraform-google-modules/terraform-google-iam//modules/service_accounts_iam"
  service_accounts = [
    module.google_test_sa.service_account.email,
  ]
  project = google_project.main.project_id
  mode    = "additive"
  bindings = {
    "roles/storage.objectAdmin" = [
      "serviceAccount:${module.google_test_sa.service_account.email}",
    ]
  }
}

Error message

Error: Invalid for_each argument

  on .terraform/modules/impersonate_service_account_iam_bindings/modules/service_accounts_iam/main.tf line 50, in resource "google_service_account_iam_member" "service_account_iam_additive":
  50:   for_each           = module.helper.set_additive

The "for_each" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the for_each depends on.

[cloudbuild] Fix parallel tests execution

Some kind of a race condition when testing buckets when running tests suites in parallel in cloud build.

× bucket-bindings: Test bucket bindings are correct
× Control Source Code Error /workspace/test/integration/authoritative/controls/authoritative.rb:97
767: unexpected token at ''

So far it looks like gsutil returns some wrong json bindings data for the buckets

Value of count error applying iam binding.

provider "google" {
  region = "${var.region}"
  credentials = "${file("./auth.json")}"
  project     = "${var.seed_project_id}"
}

provider "google-beta" {
  region = "${var.region}"
  credentials = "${file("./auth.json")}"
  project     = "${var.seed_project_id}"
}


provider "google-beta-janus" {
  region = "${var.region}"
  credentials = "${file("./auth.json")}"
  project     = "${var.seed_project_id}"
}

module "folder_iam_binding" {
  source = "terraform-google-modules/iam/google"
  mode   = "authoritative"

  folders = ["${google_folder.enironment.id}"]

  bindings = {

    "roles/editor" = [
      "${var.sysadmins}"
    ]

    "roles/editor" = [
      "${var.securityadmins}"
    ]

    "roles/viewer" = [
      "${var.developers}"
    ]

    "roles/logging.viewer" = [
      "${var.developers}"
    ]

    "roles/storage.objectViewer" = [
      "${var.developers}"
    ]

  }
}

Error: Error refreshing state: 1 error(s) occurred:

  • module.janus_environment_folder.module.folder_iam_binding.data.google_project.project_from_provider: data.google_project.project_from_provider: value of 'count' cannot be computed

The provider does specify the project. The same template worked last week and I don't have the module version pinned - so I am a little confused on what changed.

Support empty list of subnets for subnet submodule

Hi Guys,

We are currently passing in a dynamic list of subnets to the module, which fails when you supply an empty list of subnets (we have a subset of projects which don't have any subnets/networks). For example:

module "subnet-iam-bindings" {
  source = "terraform-google-modules/iam/google//modules/subnets_iam"

  subnets        = var.subnet_allows //This is empty with a value of []
  subnets_region = "australia-southeast1"
  project        = "example_vpc_host_project"
  mode           = "additive"
  bindings = {
    "roles/compute.networkUser" = [
      "user:[email protected]",
    ]
    "roles/compute.networkViewer" = [
      "user:[email protected]",
    ]
  }
}

Produces this error

Error: Error in function call

  on .terraform/modules/subnet-iam-bindings/terraform-google-modules-terraform-google-iam-01965a1/modules/helper/main.tf line 80, in locals:
  80:     ? zipmap(local.keys_additive, local.bindings_by_member)
    |----------------
    | local.bindings_by_member is empty list of dynamic
    | local.keys_additive is list of string with 2 elements

Call to function "zipmap" failed: number of keys (2) does not match number of
values (0).

It would be great if you could pass an empty list, where you have a codebase which is supplying subnets dynamically.

Error: Error in function call

For Module storage_bucket IAM, when i am trying to run this script in my cloud shell, it is showing the following errors:Error: Error in function call

I ran the script like this:

terraform apply

var.bindings

Map of role (key) and list of members (value) to add the IAM policies/bindings

Enter a value: {"storage.objectViewer"=["user:[email protected]"]}

Error: Error in function call

on ../helper/main.tf line 80, in locals:

80: ? zipmap(local.keys_additive, local.bindings_by_member)

|----------------

| local.bindings_by_member is empty list of dynamic

| local.keys_additive is list of string with 1 element

Call to function "zipmap" failed: number of keys (1) does not match number of

values (0).

module doesn't work with dynamically computed values any longer

The _num variables were removed, but apparently not with any concern over whether things will break.

I call it as such:

module "projects-iam" {
  source = "terraform-google-modules/iam/google//modules/projects_iam"

  projects     = [ local.project_id ]

  mode         = "additive"
  bindings = zipmap(
    var.project_roles,
    [ for s in var.project_roles :
        ["serviceAccount:${module.gke.service_account}"]
    ]
  )
}

where var.project_roles is a list passed in as a variable (but which is actually statically defined by the default value, which has 3 roles. But when I attempt to run it, I get the following error:

Error: Invalid for_each argument

  on .terraform/modules/projects-iam/terraform-google-modules-terraform-google-iam-45700d3/modules/projects_iam/main.tf line 44, in resource "google_project_iam_member" "project_iam_additive":
  44:   for_each = module.helper.set_additive

The "for_each" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the for_each depends on.

It worked fine when I included the _num variables for projects and bindings. It would seem that it either doesn't like a zipmap made up of constants, or else it doesn't like that it includes a string constructed from an output from another module. Either way, there doesn't seem to be a fix that works. I've tried explicitly targeting things like the service account, but that doesn't work.

Note that this occurs when I have a working gke cluster, but I made a change to the name, which forces a new cluster. When I added the call to projects-iam module to my terraform template when the GKE cluster already existed, it didn't complain. But it doesn't seem able to update both the cluster and the iam assignment at the same time - not if the name of the service account will change, anyway.

Project IAM resource is not created

Even with simple example with binding is not working for me (suppose some basic issue, but everything fine with using - resource "google_project_iam_binding" ).

Here is example:

module "iam_binding" {
  source = "terraform-google-modules/iam/google"
  
  projects = ["project"]

  mode = "additive"

  bindings = {
    "roles/storage.admin" = [
      "user:[email protected]",
    ]
  }
}

If run terraform plan (without any state):

No changes. Infrastructure is up-to-date.

if run terraform apply:

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Are there any reasons it is not recognized as a change?

Environment

Win10:

Terraform v0.12.5
+ provider.external v1.2.0
+ provider.google v2.11.0
+ provider.google-beta v2.11.0

Debug Mode log

2019/07/30 16:37:05 [DEBUG] ReferenceTransformer: "module.iam_binding.data.external.additive_bindings_temp_struct" references: []
ber.pubsub_subscription_iam_additive": starting visit (*terraform.NodePlannableResource)
2019-07-30T16:37:05.370-0700 [DEBUG] plugin: plugin process exited: path=***path***\.terraform\plugins\windows_amd64\terraform-provider-external_v1.2.0_x4.exe pid=18548
2019-07-30T16:37:05.370-0700 [DEBUG] plugin: plugin exited
2019/07/30 16:37:05 [TRACE] [walkPlan] Exiting eval tree: provider.external (close)
2019/07/30 16:37:05 [TRACE] vertex "provider.external (close)": visit complete
2019/07/30 16:37:05 [TRACE] GRPCProvider: Close
2019-07-30T16:37:05.380-0700 [DEBUG] plugin: plugin process exited: path=***path***\.terraform\plugins\windows_amd64\terraform-provider-google-beta_v2.11.0_x4.exe pid=24276
2019-07-30T16:37:05.380-0700 [DEBUG] plugin: plugin exited
2019/07/30 16:37:05 [TRACE] [walkPlan] Exiting eval tree: provider.google-beta (close)
2019/07/30 16:37:05 [TRACE] GRPCProvider: Close
2019-07-30T16:37:05.391-0700 [DEBUG] plugin: plugin process exited: path=***path***\.terraform\plugins\windows_amd64\terraform-provider-google_v2.11.0_x4.exe pid=26176

2019-07-30T16:37:05.391-0700 [DEBUG] plugin: plugin exited
2019/07/30 16:37:05 [TRACE] [walkPlan] Exiting eval tree: provider.google (close)
No changes. Infrastructure is up-to-date

Error 400: Requested policy version (1) cannot be less than the existing policy version (3)

HI,

I have following simple IAM config, which worked fine:

module "projects_iam_bindings" {
  source  = "terraform-google-modules/iam/google//modules/projects_iam"
  version = "~> 5.0"

  project = "XXX"
  mode    = "additive"

    "roles/errorreporting.user" = [
      "group:XXX@YYY",
    ]
}

But now second time totally randomly it shows this error:

Error: Error reading Resource "project \"XXX\"" with IAM Member: Role "roles/errorreporting.writer" Member "serviceAccount:[email protected]": Error retrieving IAM policy for project "XXX": googleapi: Error 400: Requested policy version (1) cannot be less than the existing policy version (3). For more information, please refer to https://cloud.google.com/iam/docs/policies#versions., badRequest

Since I didn't manually alter any IAM setting I think that there is a different issue.
It may be connected with the new condition feature, which uses IAM policy version 3. So if Google changes the policy version, the module still wants to use version 1.

What do you think about that?
I don't know how to prove this, but I hope someone here can help me.

The requested URL was not found on this server. <ins>That’s all we know.</ins>

I am trying to apply the folders_iam module, but it keeps failing on retrieving the policy.

What I do:

resource "google_folder" "folder_bootcamp" {
  display_name = "bootcamp"
  parent = "folders/${var.root_folder}"
}

module "folder-iam-bootcamp" {
  source  = "terraform-google-modules/iam/google//modules/folders_iam"
  folders = ["${google_folder.folder_bootcamp.id}"]

  mode = "authoritative"

  bindings = {
    "roles/bigquery.jobUser" = [
      "group:[email protected]",
      "group:[email protected]",
      "group:[email protected]",
    ]
    "roles/bigquery.user" = [
      "group:[email protected]",
      "group:[email protected]",
      "group:[email protected]",
    ]
    "roles/cloudsql.editor" = [
      "group:[email protected]",
      "group:[email protected]",
      "group:[email protected]",
    ]
    "roles/cloudtrace.user" = [
      "group:[email protected]",
      "group:[email protected]",
      "group:[email protected]",
    ]
    "roles/compute.viewer" = [
      "group:[email protected]",
      "group:[email protected]",
      "group:[email protected]",
    ]
    "roles/container.viewer" = [
      "group:[email protected]",
      "group:[email protected]",
      "group:[email protected]",
    ]
  }
}

But this keeps giving me errors like:

Error: Error retrieving IAM policy for folder "folders/folders/8670795366": googleapi: got HTTP response code 404 with body: <!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 404 (Not Found)!!1</title>
  <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
  </style>
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p><b>404.</b> <ins>That’s an error.</ins>
  <p>The requested URL <code>/v2/folders/folders/8670795366:getIamPolicy?alt=json&amp;prettyPrint=false</code> was not found on this server.  <ins>That’s all we know.</ins>


  on .terraform/modules/folder-iam-toolbox/terraform-google-modules-terraform-google-iam-45700d3/modules/folders_iam/main.tf line 30, in resource "google_folder_iam_binding" "folder_iam_authoritative":
  30: resource "google_folder_iam_binding" "folder_iam_authoritative" {

my assumption is that the fault lies in the fact it adds folders/ for the id that's given as an argument, which ends up showing: folders/folders/8670795366

Workload Identity Binding Issue

Hhey,

I'm trying to add bindings to service accounts for Workload Identity through the module in the following way:

module "vault_service_account" {
  source  = "terraform-google-modules/service-accounts/google"
  version = "2.0.2"

  # Project to create service account in
  project_id = data.terraform_remote_state.project_in_scope.outputs.project_id

  names = [
    "${var.project_prefix}-vault"
  ]

  #Service account should only have permissions for KMS (encryption keys) & storage
  project_roles = [
    "${data.terraform_remote_state.project_in_scope.outputs.project_id}=>roles/cloudkms.cryptoKeyEncrypterDecrypter",
    "${data.terraform_remote_state.project_in_scope.outputs.project_id}=>roles/storage.objectAdmin"
  ]
}
module "vault_iam_service_accounts_iam" {
  source  = "terraform-google-modules/iam/google//modules/service_accounts_iam"
  version = "6.1.0"

  service_accounts = [
    module.vault_service_account.email
  ]

  project = data.terraform_remote_state.project_in_scope.outputs.project_id

  mode = "authoritative"

  bindings = {
    "roles/iam.workloadIdentityUser" = [
      "serviceAccount:${data.terraform_remote_state.project_in_scope.outputs.project_id}.svc.id.goog[vault/services]"
    ]
  }
}

When I try running this, I'm getting the following error:

Error: Error applying IAM policy for service account 'projects/reference-cde-47d5/serviceAccounts/[email protected]': Error setting IAM policy for service account 'projects/reference-cde-47d5/serviceAccounts/[email protected]': googleapi: Error 400: Identity namespace does not exist (reference-cde-47d5.svc.id.goog)., badRequest

  on .terraform/modules/loki_iam_service_accounts_iam/terraform-google-iam-6.1.0/modules/service_accounts_iam/main.tf line 30, in resource "google_service_account_iam_binding" "service_account_iam_authoritative":     
  30: resource "google_service_account_iam_binding" "service_account_iam_authoritative" {

What I find weird (and the reason I'm creating the issue) is that if I run the gcloud equivalent:
gcloud iam service-accounts add-iam-policy-binding --role roles/iam.workloadIdentityUser --member "serviceAccount:reference-cde-47d5.svc.id.goog[vault/services]" [email protected]

Everything works successfully:

Updated IAM policy for serviceAccount [[email protected]].
bindings:
- members:
  - serviceAccount:reference-cde-47d5.svc.id.goog[vault/services]
  role: roles/iam.workloadIdentityUser
etag: BwWmLtVTJtE=
version: 1

Finally, I also checked that the Identity namespace is correctly created when creating the cluster and the SA/binding combo are created after the cluster is finished creating.

My question is, do I have to do some specific configuration inside the module or is there an underlying issue that might be preventing this? (both the SA and the binding are created in the same terraform file and the SA is guaranteed to be created first via depends_on in the outputs).

for_each rewrite

Hi,

It is still a work in progress, but I have started re-writing this module with for_each to work around the count limitations and avoid bindings re-creation when the input map changes:
https://github.com/sleterrier/terraform-google-iam

I don't think the Issues board is the best place for this, but I thought you might be interested in seeing this new >=0.12.6 approach.

Do not use authoritative mode in examples

At multiple clients individuals working with Terraform that are of limited experience are copying the examples block and modifying it to fit their use case. The default use of authoritative=true has caused massive headaches multiple times. To clarify demonstrating it's there is beneficial, but please consider the volume of users that will copy/paste without fully understanding the implications of their actions. Yes the users should understand the module, but it would still be appreciated.

This is primarily an enhancement and an quality of life change if possible. Thanks.

Release 6.3.0: Blocks of type "condition" are not expected here.

Terraform v0.12.28

  • provider.google v3.29.0
    IAM module version: 6.3.0

On Terraform validate:

Error: Unsupported block type

on .terraform/modules/organization-iam-bindings/modules/organizations_iam/main.tf line 36, in resource "google_organization_iam_binding" "organization_iam_authoritative":
36: dynamic "condition" {

Blocks of type "condition" are not expected here.

Error: Unsupported block type

on .terraform/modules/organization-iam-bindings/modules/organizations_iam/main.tf line 54, in resource "google_organization_iam_member" "organization_iam_additive":
54: dynamic "condition" {

Blocks of type "condition" are not expected here.

Error: Unsupported block type

on .terraform/modules/prod-folder/modules/folders_iam/main.tf line 36, in resource "google_folder_iam_binding" "folder_iam_authoritative":
36: dynamic "condition" {

Blocks of type "condition" are not expected here.

Error: Unsupported block type

on .terraform/modules/prod-folder/modules/folders_iam/main.tf line 54, in resource "google_folder_iam_member" "folder_iam_additive":
54: dynamic "condition" {

Blocks of type "condition" are not expected here.


If I use the version 6.2 in the code it is working perfectly fine and I am not using any conditions.

My sample code Not working:

module "organization-iam-bindings" {
source = "terraform-google-modules/iam/google//modules/organizations_iam"
organizations = [var.org_id]
mode = "additive"
bindings = var.org_iam_bindings
}


My sample code working:

module "organization-iam-bindings" {
source = "terraform-google-modules/iam/google//modules/organizations_iam"
version = "= 6.2"
organizations = [var.org_id]
mode = "additive"
bindings = var.org_iam_bindings
}


organizations_iam: "Role roles/securityReviewer is not supported for this resource"

Given the following code...

module "org_iam" {
  source        = "../../modules/iam/modules/organizations_iam"
  organizations = ["99999999"]
  mode          = "additive"
  bindings = {
    "roles/resourcemanager.organizationAdmin" = ["serviceAccount:[email protected]"]
    "roles/securityReviewer"                  = ["serviceAccount:[email protected]"]
  }
}

I'm getting this error...

Error: Error applying IAM policy for organization "99999999": Error setting IAM policy for organization "99999999": googleapi: Error 400: Role roles/securityReviewer is not supported for this resource., badRequest

  on ../../modules/iam/modules/organizations_iam/main.tf line 40, in resource "google_organization_iam_member" "organization_iam_additive":
  40: resource "google_organization_iam_member" "organization_iam_additive" {

When I go into GCP's IAM page, I was able to assign that role manually to that service account without error.

The other binding (roles/resourcemanager.organizationAdmin) works fine, but I'm not sure why it's failing on just roles/securityReviewer. Using authoritative mode yields the same result.

Can you share some insight on this on how I might be able to fix this?

Thank you.

Refactor helper module to force order

Refactor generation of bindings_authoritative and bindings_additive in modules/helper/main.tf to force the order between them. Highly recommended to make the logic behind more resilient to future code updates.

Error: command "bash" produced invalid JSON

I think there may be an issue with a change to this line from #32:

echo "$OUTPUT"| sed -e 's/.*/{\n "data": "&/; s/$/"\n}/'

I'm trying out the changes from #44 which incorporate this change and was getting the following error:

Error: command "bash" produced invalid JSON: invalid character 'n' looking for beginning of object key string

  on .terraform/modules/project_iam_binding/main.tf line 83, in data "external" "additive_bindings_temp_struct":
  83: data "external" "additive_bindings_temp_struct" {

When I swapped this line back to the old version in the downloaded module it worked:

jq -n --arg output "$OUTPUT" '{data:$output}'

The following should reproduce the issue:

module "project_iam_binding" {
  source  = "git::https://github.com/terraform-google-modules/terraform-google-iam.git"
  projects = ["my-project"]

  bindings = {
    "roles/storage.admin" = [
      "user:[email protected]",
    ]
  }
}

Let me know if there are any other details I can provide.

data.external.additive_bindings_temp_struct: failed to execute "bash" Argument list too long

Getting the an error while executing tf plan -var-file terraform.tfvars

The iam.tf file looks like this:

module "iam" {
  source  = "github.com/terraform-google-modules/terraform-google-iam?ref=v1.0.0"
  version = "1.0.0"
  providers = {
    google = "google-beta"
  }
  project = "${var.project_id}"

  mode = "additive"

  service_accounts = [
    "serviceAccount:0@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:1@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:2@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:3@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:4@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:5@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:6@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:7@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:8@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:9@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:10@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:11@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:12@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:13@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:14@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:15@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:16@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:17@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:18@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:19@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:20@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:21@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:22@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:23@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:24@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:25@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:26@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:27@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:28@${var.project_id}.iam.gserviceaccount.com",
    "serviceAccount:29@${var.project_id}.iam.gserviceaccount.com"
  ]

  bindings = {

    "roles/logging.logWriter" = [
      "serviceAccount:0@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:1@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:2@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:3@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:4@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:5@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:6@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:7@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:8@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:9@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:10@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:11@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:12@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:13@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:14@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:15@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:16@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:17@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:18@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:19@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:20@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:21@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:22@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:23@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:24@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:25@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:26@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:27@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:28@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:29@${var.project_id}.iam.gserviceaccount.com"
    ]

    "roles/monitoring.metricWriter" = [
      "serviceAccount:0@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:1@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:2@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:3@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:4@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:5@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:6@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:7@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:8@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:9@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:10@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:11@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:12@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:13@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:14@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:15@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:16@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:17@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:18@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:19@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:20@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:21@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:22@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:23@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:24@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:25@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:26@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:27@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:28@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:29@${var.project_id}.iam.gserviceaccount.com"
    ]

    "roles/monitoring.viewer" = [
      "serviceAccount:0@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:1@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:2@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:3@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:4@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:5@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:6@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:7@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:8@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:9@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:10@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:11@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:12@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:13@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:14@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:15@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:16@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:17@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:18@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:19@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:20@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:21@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:22@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:23@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:24@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:25@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:26@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:27@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:28@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:29@${var.project_id}.iam.gserviceaccount.com"
    ]

    "roles/cloudtrace.agent" = [
      "serviceAccount:0@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:1@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:2@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:3@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:4@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:5@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:6@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:7@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:8@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:9@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:10@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:11@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:12@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:13@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:14@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:15@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:16@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:17@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:18@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:19@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:20@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:21@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:22@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:23@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:24@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:25@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:26@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:27@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:28@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:29@${var.project_id}.iam.gserviceaccount.com"
    ]

    "roles/storage.objectViewer" = [
      "serviceAccount:0@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:1@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:2@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:3@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:4@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:5@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:6@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:7@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:8@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:9@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:10@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:11@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:12@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:13@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:22@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:23@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:24@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:25@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:26@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:27@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:28@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:29@${var.project_id}.iam.gserviceaccount.com"
    ]

    "roles/cloudsql.editor" = [
      "serviceAccount:0@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:1@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:2@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:3@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:4@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:5@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:6@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:7@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:8@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:9@${var.project_id}.iam.gserviceaccount.com"
    ]

    "roles/bigquery.user" = [
      "serviceAccount:3@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:9@${var.project_id}.iam.gserviceaccount.com"
    ]

    "roles/bigquery.dataOwner" = [
      "serviceAccount:6@${var.project_id}.iam.gserviceaccount.com",
      "serviceAccount:7@${var.project_id}.iam.gserviceaccount.com"
    ]

    "roles/storage.objectAdmin" = [
      "serviceAccount:14@${var.project_id}.iam.gserviceaccount.com",
    ]

  }
}

Running a plan got 1 error:

$ tf plan -var-file terraform.tfvars                                                                                                                                                        
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

data.external.additive_bindings_temp_struct: Refreshing state...

Error: Error refreshing state: 1 error(s) occurred:

* module.iam.data.external.additive_bindings_temp_struct: 1 error(s) occurred:

* module.iam.data.external.additive_bindings_temp_struct: data.external.additive_bindings_temp_struct: failed to execute "bash": /Users/project/.terraform/modules/a4dd812b5e5800e40cffd6c5f897b691/scripts/create_additive_authoritative_structures.sh: line 154: /usr/local/bin/jq: Argument list too long

Standardize integration testing

The integration testing for this module should be standardized based on the module template. This should include removal of the custom Docker image and obviating the need for manual steps beyond running kitchen.

Adding new bindings is a destructive operation

Version 1.0.0

When used with mode = "authoritative", when adding a new binding the module will sometimes attempt to delete one or more of the existing bindings. It then attempts to re-create them. The deletion events occur before any of the creation events and the delay between deletion and creation of bindings can be on the order of minutes.

This is problematic when used on production systems. The time between bindings being deleted and re-created is long enough that live workloads could experience IAM permission errors.

Ideally, adding new bindings would be a purely additive operation. Alternatively, if the delay between deletion and creation of bindings could be constrained to seconds instead of minutes, the risk to production systems would be minimized.

setting IAM project owner role fails.

While creating a fresh new project and adding a gmail user ID as a project owner through IAM role "roles/owner", request fails with the following error :

Error: Request "Create IAM Members roles/owner user:[email protected] for "project \"xxxx\""" returned error: Error applying IAM policy for project "es-bernasos": Error setting IAM policy for project "xxxx": googleapi: Error 400: Request contains an invalid argument., badRequest.

Assumption :
IAM Role "roles/owner" requires initating an invitation workflow which results an error through API

Error upgrading the module version.

terraform --version
Terraform v0.12.19
+ provider.external v1.2.0
+ provider.google v3.5.0
+ provider.google-beta v3.5.0
+ provider.null v2.1.2
+ provider.random v2.2.1

the mentioned bucket does exist.

module "storage_buckets_iam_bindings" {
  source  = "terraform-google-modules/iam/google//modules/storage_buckets_iam"
  version = "5.1" # used to be ~ 4.0

  storage_buckets = [google_storage_bucket.staging_bucket_tools.id]

  mode = "additive"

  bindings = {
    "roles/storage.legacyBucketReader" = [
      module.external_service_accounts.janus_deploy_service_account,
    ]

    "roles/storage.objectAdmin" = [
      module.external_service_accounts.janus_deploy_service_account,
    ]

    "roles/storage.objectViewer" = [
      module.external_service_accounts.janus_deploy_service_account,
      module.data_pipeline_project.cloud_functions_service_account,
      "serviceAccount:${module.data_pipeline_project.project_number}@cloudservices.gserviceaccount.com",
    ]
  }

terraform apply

causes

Error: Invalid for_each argument

  on .terraform/modules/hsq-dev.storage_buckets_iam_bindings/terraform-google-modules-terraform-google-iam-01965a1/modules/storage_buckets_iam/main.tf line 41, in resource "google_storage_bucket_iam_member" "storage_bucket_iam_additive":
  41:   for_each = module.helper.set_additive

The "for_each" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the for_each depends on.

Provider doesn't support resource: google_compute_subnetwork_iam_member

Hi,

I am trying to use terraform and this iam module to create a few service accounts but getting errors:

ye@mac $ tf version 
Terraform v0.11.13
+ provider.external v1.1.1
+ provider.google v2.4.0
+ provider.kubernetes v1.6.2

ye@mac $ tf init                                                                                                                                                                                       
Initializing modules...
- module.iam

Initializing provider plugins...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.external: version = "~> 1.1"
* provider.kubernetes: version = "~> 1.6"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
 
ye@mac $ tf plan                                                                                               

Warning: google_container_cluster.primary: "zone": [DEPRECATED] Use location instead



Warning: google_container_node_pool.admin_support_pool: "zone": [DEPRECATED] use location instead



Warning: google_container_node_pool.cache_pool: "zone": [DEPRECATED] use location instead



Warning: google_container_node_pool.cron_pool: "zone": [DEPRECATED] use location instead



Warning: google_container_node_pool.stateless_dataprocess_pool: "zone": [DEPRECATED] use location instead



Warning: google_container_node_pool.stateless_pool: "zone": [DEPRECATED] use location instead



Warning: google_container_node_pool.stateless_worker_pool: "zone": [DEPRECATED] use location instead



Warning: google_container_node_pool.support_pool: "zone": [DEPRECATED] use location instead



Error: module.iam.google_compute_subnetwork_iam_binding.subnet_iam_authoritative: Provider doesn't support resource: google_compute_subnetwork_iam_binding



Error: module.iam.google_compute_subnetwork_iam_member.subnet_iam_additive: Provider doesn't support resource: google_compute_subnetwork_iam_member

Error: module.iam.google_compute_subnetwork_iam_member.subnet_iam_additive: Provider doesn't support resource: google_compute_subnetwork_iam_member

ye@mac $ cat svc-acct.tf
data "google_service_account" "foobar" {
  account_id = "foobar-pod-sa"
}

resource "google_service_account_key" "foobar_key" {
  service_account_id = "${data.google_service_account.foobar.name}"
}

resource "kubernetes_secret" "gac_foobar" {
  metadata = {
    name = "gac-foobar"
  }
  data {
    credentials.json = "${base64decode(google_service_account_key.foobar_key.private_key)}"
  }
}

So what did I do wrong here?

Error using on the bucket that does not exist yet.

resource "google_storage_bucket" "logsinc_bucket_tools" {
  name    = "${var.environment_name}-log-sink"
  project = data.google_project.tools_project.project_id
}

module "logsinc_bucket_iam_bindings" {
  source  = "terraform-google-modules/iam/google//modules/storage_buckets_iam"
  version = "~> 3.0"

  storage_buckets = [google_storage_bucket.logsinc_bucket_tools.id]

  mode = "additive"

  bindings = {
    "roles/storage.objectCreator" = [
      "group:[email protected]",
    ]

    "roles/storage.objectViewer" = [
      "group:[email protected]",
    ]
  }
}

Causes an error:

Error: Invalid count argument

on .terraform/modules/hsq-uat.logsinc_bucket_iam_bindings/terraform-google-modules-terraform-google-iam-ace2efe/modules/storage_buckets_iam/main.tf line 45, in resource "google_storage_bucket_iam_member" "storage_bucket_iam_additive":
45: count = var.bindings_num > 0 ? var.bindings_num * local.additive * local.storage_bucket_count : length(local.bindings_formatted) * local.additive

Allow referencing computed values

As documented here, the module currently fails when using computed inputs (such as Service Accounts created by Terraform).

Fixing this has two parts:

  • Allow referencing computed values in the base resource target (ie. projects, folders, etc.)
  • Allow referencing computed values in the bindings themselves (ex. to reference service account emails)

Failed to download module

Hi,

I have a module where I am using 'projects_iam'

module "projects_iam_bindings" { source = "terraform-google-modules/iam/google//modules/projects_iam" version = "~> 6.3" mode = "additive" projects = var.projects bindings = var.bindings }

It worked fine in one instance. I now moved to a new instance , terraform is now giving 'Failed to download module' issue.

Error: Failed to download module

Could not download module "projects_iam_bindings" (../modules/iam/project-bindings/main.tf:8) source code from "git::https://github.com/terraform-google-modules/terraform-google-iam?ref=v6.3.1": error downloading 'https://github.com/terraform-google-modules/terraform-google-iam?ref=v6.3.1': /usr/bin/git exited with 1: error: pathspec 'v6.3.1' did not match any file(s) known to git.

Can someone please let me know , what the problem is ?

Thanks.

Warnings of deprecated features in output

When running a successful terraform plan the following stdout is returned.

Warning: module.iam_binding.google_compute_subnetwork_iam_binding.subnet_iam_authoritative: "project": [DEPRECATED] This resource is in beta and will be removed from this provider. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.

Warning: module.iam_binding.google_compute_subnetwork_iam_binding.subnet_iam_authoritative: "region": [DEPRECATED] This resource is in beta and will be removed from this provider. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.

Warning: module.iam_binding.google_compute_subnetwork_iam_binding.subnet_iam_authoritative: "subnetwork": [DEPRECATED] This resource is in beta and will be removed from this provider. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.

Warning: module.iam_binding.google_compute_subnetwork_iam_member.subnet_iam_additive: "project": [DEPRECATED] This resource is in beta and will be removed from this provider. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.

Warning: module.iam_binding.google_compute_subnetwork_iam_member.subnet_iam_additive: "region": [DEPRECATED] This resource is in beta and will be removed from this provider. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.

Warning: module.iam_binding.google_compute_subnetwork_iam_member.subnet_iam_additive: "subnetwork": [DEPRECATED] This resource is in beta and will be removed from this provider. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/provider_versions.html for more details.

Double folders/ path

I just tried to run folder permissions and got the following:

Error retrieving IAM policy for folder "folders/folders/XXXXXXXXXX": googleapi: got HTTP response code 404 with body: <!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 404 (Not Found)!!1</title>
  <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
  </style>
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p><b>404.</b> <ins>That’s an error.</ins>
  <p>The requested URL <code>/v2/folders/folders/XXXXXXXXXX:getIamPolicy?alt=json&amp;prettyPrint=false</code> was not found on this server.  <ins>That’s all we know.</ins>


  on .terraform\modules\iam_folder.iam\terraform-google-modules-terraform-google-iam-ace2efe\modules\folders_iam\main.tf line 44, in resource "google_folder_iam_member" "folder_iam_additive":
  44: resource "google_folder_iam_member" "folder_iam_additive" {

Scripts

./main.tf

provider "google" {
  version = "~> 2.17"
  region      = "${var.gcp_region}"
  credentials = "${file("${var.gcp_credentials}")}"
}

resource "google_folder" "the_folder" {
  display_name = "the-folder"
  parent       = "XXXXXX"
}

module "iam_folder" {
  source         = "./modules/folder-iam-policy"
  folder_ids     = [google_folder.the_folder.id]
  folders_num    = 1
  editor_members = ["[email protected]"]
  admin_members  = ["[email protected]"]
  viewer_members = ["[email protected]"]
}

./modules/folder-iam-policy/main.tf

module "iam" {
  source = "terraform-google-modules/iam/google//modules/folders_iam"
  version = "~> 3.0"
  folders = var.folder_ids
  folders_num = var.folders_num
  bindings = {
    # explicit viewer_members
    "roles/compute.instanceAdmin"          = var.admin_members
    "roles/bigquery.admin"                 = var.admin_members
    "roles/resourcemanager.folderAdmin"    = var.admin_members
    "roles/resourcemanager.folderIamAdmin" = var.admin_members

    
    "roles/resourcemanager.folderViewer"       = flatten([var.editor_members, var.viewer_members])
  }
}

./modules/folder-iam-policy/variables.tf

variable admin_members {
  default = []
  type    = list(string)
}
variable viewer_members {
  default = []
  type    = list(string)
}
variable editor_members {
  default = []
  type    = list(string)
}

variable folder_ids {
  default = []
  type    = list(string)
} 

variable folders_num {
  default = 0
}

Fix adding new bindings in additive mode

Hi,

It seems that when you add a new project binding in additive mode, the module destroys everything and recreates all bindings from scratch. It would be better if the module adds only new binding to the Terraform state.

Envinronemt

Terraform v0.12.4
+ provider.external v1.2.0
+ provider.google v2.10.0
+ provider.google-beta v2.10.0

Current behaviour

Firstly, I have the following Terraform code:

module "bindings" {
  source   = "terraform-google-modules/iam/google"
  version  = "2.0.0"
  projects = [var.project]

  mode = "additive"

  bindings = {
    "roles/bigquery.dataViewer" = [
      "serviceAccount:service-account-0@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-1@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-2@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-3@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-4@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-5@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-6@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-7@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-8@${var.project}.iam.gserviceaccount.com",
    ]
  }
}

When I apply the changes and call terraform state list I can see the following list:

module.bindings.data.external.additive_bindings_temp_struct
module.bindings.google_project_iam_member.project_iam_additive[0]
module.bindings.google_project_iam_member.project_iam_additive[1]
module.bindings.google_project_iam_member.project_iam_additive[2]
module.bindings.google_project_iam_member.project_iam_additive[3]
module.bindings.google_project_iam_member.project_iam_additive[4]
module.bindings.google_project_iam_member.project_iam_additive[5]
module.bindings.google_project_iam_member.project_iam_additive[6]
module.bindings.google_project_iam_member.project_iam_additive[7]
module.bindings.google_project_iam_member.project_iam_additive[8]

Then, when I want to add a service account (as you can see, only serviceAccount:service-account-9@${var.project}.iam.gserviceaccount.com is added) to existing binding:

module "bindings" {
  source   = "terraform-google-modules/iam/google"
  version  = "2.0.0"
  projects = [var.project]

  mode = "additive"

  bindings = {
    "roles/bigquery.dataViewer" = [
      "serviceAccount:service-account-0@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-1@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-2@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-3@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-4@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-5@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-6@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-7@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-8@${var.project}.iam.gserviceaccount.com",
      "serviceAccount:service-account-9@${var.project}.iam.gserviceaccount.com",
    ]
  }
}

and call terraform plan I get the following output:

Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

module.bindings.data.external.additive_bindings_temp_struct: Refreshing state...
module.bindings.google_project_iam_member.project_iam_additive[2]: Refreshing state... [id=<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-6@<my-gcp-project>.iam.gserviceaccount.com]
module.bindings.google_project_iam_member.project_iam_additive[0]: Refreshing state... [id=<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-8@<my-gcp-project>.iam.gserviceaccount.com]
module.bindings.google_project_iam_member.project_iam_additive[6]: Refreshing state... [id=<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-2@<my-gcp-project>.iam.gserviceaccount.com]
module.bindings.google_project_iam_member.project_iam_additive[4]: Refreshing state... [id=<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-4@<my-gcp-project>.iam.gserviceaccount.com]
module.bindings.google_project_iam_member.project_iam_additive[1]: Refreshing state... [id=<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-7@<my-gcp-project>.iam.gserviceaccount.com]
module.bindings.google_project_iam_member.project_iam_additive[7]: Refreshing state... [id=<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-1@<my-gcp-project>.iam.gserviceaccount.com]
module.bindings.google_project_iam_member.project_iam_additive[3]: Refreshing state... [id=<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-5@<my-gcp-project>.iam.gserviceaccount.com]
module.bindings.google_project_iam_member.project_iam_additive[5]: Refreshing state... [id=<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-3@<my-gcp-project>.iam.gserviceaccount.com]
module.bindings.google_project_iam_member.project_iam_additive[8]: Refreshing state... [id=<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-0@<my-gcp-project>.iam.gserviceaccount.com]

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # module.bindings.google_project_iam_member.project_iam_additive[0] must be replaced
-/+ resource "google_project_iam_member" "project_iam_additive" {
      ~ etag    = "GfHM97ODu3h=" -> (known after apply)
      ~ id      = "<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-8@<my-gcp-project>.iam.gserviceaccount.com" -> (known after apply)
      ~ member  = "serviceAccount:service-account-8@<my-gcp-project>.iam.gserviceaccount.com" -> "serviceAccount:service-account-9@<my-gcp-project>.iam.gserviceaccount.com" # forces replacement
        project = "<my-gcp-project>"
        role    = "roles/bigquery.dataViewer"
    }

  # module.bindings.google_project_iam_member.project_iam_additive[1] must be replaced
-/+ resource "google_project_iam_member" "project_iam_additive" {
      ~ etag    = "GfHM97ODu3h=" -> (known after apply)
      ~ id      = "<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-7@<my-gcp-project>.iam.gserviceaccount.com" -> (known after apply)
      ~ member  = "serviceAccount:service-account-7@<my-gcp-project>.iam.gserviceaccount.com" -> "serviceAccount:service-account-8@<my-gcp-project>.iam.gserviceaccount.com" # forces replacement
        project = "<my-gcp-project>"
        role    = "roles/bigquery.dataViewer"
    }

  # module.bindings.google_project_iam_member.project_iam_additive[2] must be replaced
-/+ resource "google_project_iam_member" "project_iam_additive" {
      ~ etag    = "GfHM97ODu3h=" -> (known after apply)
      ~ id      = "<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-6@<my-gcp-project>.iam.gserviceaccount.com" -> (known after apply)
      ~ member  = "serviceAccount:service-account-6@<my-gcp-project>.iam.gserviceaccount.com" -> "serviceAccount:service-account-7@<my-gcp-project>.iam.gserviceaccount.com" # forces replacement
        project = "<my-gcp-project>"
        role    = "roles/bigquery.dataViewer"
    }

  # module.bindings.google_project_iam_member.project_iam_additive[3] must be replaced
-/+ resource "google_project_iam_member" "project_iam_additive" {
      ~ etag    = "GfHM97ODu3h=" -> (known after apply)
      ~ id      = "<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-5@<my-gcp-project>.iam.gserviceaccount.com" -> (known after apply)
      ~ member  = "serviceAccount:service-account-5@<my-gcp-project>.iam.gserviceaccount.com" -> "serviceAccount:service-account-6@<my-gcp-project>.iam.gserviceaccount.com" # forces replacement
        project = "<my-gcp-project>"
        role    = "roles/bigquery.dataViewer"
    }

  # module.bindings.google_project_iam_member.project_iam_additive[4] must be replaced
-/+ resource "google_project_iam_member" "project_iam_additive" {
      ~ etag    = "GfHM97ODu3h=" -> (known after apply)
      ~ id      = "<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-4@<my-gcp-project>.iam.gserviceaccount.com" -> (known after apply)
      ~ member  = "serviceAccount:service-account-4@<my-gcp-project>.iam.gserviceaccount.com" -> "serviceAccount:service-account-5@<my-gcp-project>.iam.gserviceaccount.com" # forces replacement
        project = "<my-gcp-project>"
        role    = "roles/bigquery.dataViewer"
    }

  # module.bindings.google_project_iam_member.project_iam_additive[5] must be replaced
-/+ resource "google_project_iam_member" "project_iam_additive" {
      ~ etag    = "GfHM97ODu3h=" -> (known after apply)
      ~ id      = "<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-3@<my-gcp-project>.iam.gserviceaccount.com" -> (known after apply)
      ~ member  = "serviceAccount:service-account-3@<my-gcp-project>.iam.gserviceaccount.com" -> "serviceAccount:service-account-4@<my-gcp-project>.iam.gserviceaccount.com" # forces replacement
        project = "<my-gcp-project>"
        role    = "roles/bigquery.dataViewer"
    }

  # module.bindings.google_project_iam_member.project_iam_additive[6] must be replaced
-/+ resource "google_project_iam_member" "project_iam_additive" {
      ~ etag    = "GfHM97ODu3h=" -> (known after apply)
      ~ id      = "<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-2@<my-gcp-project>.iam.gserviceaccount.com" -> (known after apply)
      ~ member  = "serviceAccount:service-account-2@<my-gcp-project>.iam.gserviceaccount.com" -> "serviceAccount:service-account-3@<my-gcp-project>.iam.gserviceaccount.com" # forces replacement
        project = "<my-gcp-project>"
        role    = "roles/bigquery.dataViewer"
    }

  # module.bindings.google_project_iam_member.project_iam_additive[7] must be replaced
-/+ resource "google_project_iam_member" "project_iam_additive" {
      ~ etag    = "GfHM97ODu3h=" -> (known after apply)
      ~ id      = "<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-1@<my-gcp-project>.iam.gserviceaccount.com" -> (known after apply)
      ~ member  = "serviceAccount:service-account-1@<my-gcp-project>.iam.gserviceaccount.com" -> "serviceAccount:service-account-2@<my-gcp-project>.iam.gserviceaccount.com" # forces replacement
        project = "<my-gcp-project>"
        role    = "roles/bigquery.dataViewer"
    }

  # module.bindings.google_project_iam_member.project_iam_additive[8] must be replaced
-/+ resource "google_project_iam_member" "project_iam_additive" {
      ~ etag    = "GfHM97ODu3h=" -> (known after apply)
      ~ id      = "<my-gcp-project>/roles/bigquery.dataViewer/serviceaccount:service-account-0@<my-gcp-project>.iam.gserviceaccount.com" -> (known after apply)
      ~ member  = "serviceAccount:service-account-0@<my-gcp-project>.iam.gserviceaccount.com" -> "serviceAccount:service-account-1@<my-gcp-project>.iam.gserviceaccount.com" # forces replacement
        project = "<my-gcp-project>"
        role    = "roles/bigquery.dataViewer"
    }

  # module.bindings.google_project_iam_member.project_iam_additive[9] will be created
  + resource "google_project_iam_member" "project_iam_additive" {
      + etag    = (known after apply)
      + id      = (known after apply)
      + member  = "serviceAccount:service-account-0@<my-gcp-project>.iam.gserviceaccount.com"
      + project = "<my-gcp-project>"
      + role    = "roles/bigquery.dataViewer"
    }

Plan: 10 to add, 0 to change, 9 to destroy.

------------------------------------------------------------------------

This plan was saved to: terraform.plan

To perform exactly these actions, run the following command to apply:
    terraform apply "terraform.plan"

Expected behaviour

It would be better, if Terraform will create a new binding. In this case for role roles/bigquery.dataViewer assign a member serviceAccount:service-account-9@<my-gcp-project>.iam.gserviceaccount.com:

# module.bindings.google_project_iam_member.project_iam_additive[9] will be created
+ resource "google_project_iam_member" "project_iam_additive" {
    + etag    = (known after apply)
    + id      = (known after apply)
    + member  = "serviceAccount:service-account-9@<my-gcp-project>.iam.gserviceaccount.com"
    + project = "<my-gcp-project>"
    + role    = "roles/bigquery.dataViewer"
  }

Support empty map of bindings for all submodules

Hi,
We are currently passing in a dynamic list of bindings to the module, which fails when you supply an empty maps of bindings (we have a some projects and folders which don't have any IAM permissions). For example:

module "projects_iam_bindings" {
source = "terraform-google-modules/iam/google//modules/projects_iam"
version = "~> 3.0"
projects = [google_project.my_project.project_id]
mode = "additive"
bindings = module.iambind.project_bindings
}

module iambind (custom module) may or may not return It would be great if you could pass an empty maps, where you have a codebase which is supplying bindings dynamically.

'Call to function "coalescelist" failed: no non-null arguments ' on terraform import

Hi,

I'm trying to import existing IAM bindings into the terraform state using this google-iam module. My terraform configuration is as follows:

module "main_organization_iam_binding" {
    source = "terraform-google-modules/iam/google"

    organizations = [var.organization_id]

    mode = "authoritative"

    bindings = {
        "roles/resourcemanager.folderAdmin" = [
            "user:[email protected]",
            "user:[email protected]"
        ]
    }
}

The value for organization_id variable is defined in a terraform.tfvars file. When I terraform plan this config, I see that the resource that will be created for the folderAdmin binding is the following:

module.main_organization_iam_binding.google_organization_iam_binding.organization_iam_authoritative[0]

So, I try to run the following import statement:

terraform import 'module.main_organization_iam_binding.google_organization_iam_binding.organization_iam_authoritative[0]' "<org_id> roles/resourcemanager.folderAdmin"

But this generates the following error message:

Error: Error in function call

  on .terraform/modules/main_organization_iam_binding/terraform-google-modules-terraform-google-iam-96813bd/main.tf line 53, in locals:
  53:   objects_affected = coalescelist(
  54: 
  55: 
  56: 
  57: 
  58: 
  59: 
  60: 
  61: 
  62: 
  63: 
  64: 
    |----------------
    | var.folders is empty list of string
    | var.kms_crypto_keys is empty list of string
    | var.kms_key_rings is empty list of string
    | var.organizations is empty list of dynamic
    | var.projects is empty list of string
    | var.pubsub_subscriptions is empty list of string
    | var.pubsub_topics is empty list of string
    | var.service_accounts is empty list of string
    | var.storage_buckets is empty list of string
    | var.subnets is empty list of string

Call to function "coalescelist" failed: no non-null arguments.

Any ideas on how to make this work?

Failed to download module

Anyone else seeing this?

Error: Failed to download module

Could not download module "project_iam_bindings"
(../../../modules/infra-project-iam/main.tf:6) source code from
"https://api.github.com/repos/terraform-google-modules/terraform-google-iam/tarball/v5.1.0//*?archive=tar.gz":

Importing module as:

module "project_iam_bindings" {
  source   = "terraform-google-modules/iam/google//modules/projects_iam"

Error applying to a folder.

module "folder_iam_binding" {
  source = "terraform-google-modules/iam/google"
  mode   = "authoritative"

  folders = ["${google_folder.enironment.id}"]

  bindings = {

    "roles/editor" = [
      "${var.sysadmins}"
    ]

    "roles/viewer" = [
      "${var.developers}"
    ]

    "roles/logViewer" = [
      "${var.developers}"
    ]

    "roles/storageObjectViewer" = [
      "${var.developers}"
    ]

  }
}

produces an error:

  • module.janus_environment_folder.module.folder_iam_binding.google_folder_iam_binding.folder_iam_authoritative[2]: 1 error(s) occurred:

  • google_folder_iam_binding.folder_iam_authoritative.2: Error retrieving IAM policy for folder "folders/folders/999577761704": googleapi: got HTTP response code 404 with body:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.