GoogleCloudPlatform / pbmm-on-gcp-onboarding

GCP Canadian Public Sector Landing Zone overlay on top of the TEF via CFT modules - a secure cloud foundation
https://cloud.google.com/architecture/security-foundations
Apache License 2.0
41 stars 55 forks source link

Add IAM leveled secondary admin/read-only group permissions hierarchy to workloads projects for tiered CI/CD #271

Closed obriensystems closed 4 months ago

obriensystems commented 1 year ago

20230808: todo: add project level iam access to https://github.com/GoogleCloudPlatform/pbmm-on-gcp-onboarding/blob/main/environments/common/iam-groups.auto.tfvars#L18

In addition to #263 add alternate admin permissions to workload projects

Opinionated groups gexample

ProdOpsAdmin group

ProdRead group

ProdTelcoAdmin group

ProdSecAdmin group

ProdBilling group

Similar to the TEF or TOC default groups

Screenshot 2023-08-01 at 22 39 00 Screenshot 2023-08-01 at 22 38 27

or kcc groups https://github.com/GoogleCloudPlatform/pubsec-declarative-toolkit/blob/main/solutions/guardrails/configs/iam/group-iam.yaml

obriensystems commented 1 year ago

Work Items

obriensystems commented 1 year ago

testing gcloud

Screenshot 2023-08-01 at 22 48 52 Screenshot 2023-08-01 at 22 49 21
michael@cloudshell:~ (vpc-host-nonprod-hh015-gz357)$ gcloud identity groups create security@ob...are --organization="obri...re" --group-type="security" --display-name="Security Group" --description="Description of Security Group"
API [cloudresourcemanager.googleapis.com] not enabled on project [476118442898]. Would you like to enable and retry (this will take a few minutes)? (y/N)?  y

Enabling service [cloudresourcemanager.googleapis.com] on project [476118442898]...
Operation "operations/acat.p2-476118442898-57a388fd-596a-4582-aa18-6a22d8c2270f" finished successfully.
API [cloudidentity.googleapis.com] not enabled on project [476118442898]. Would you like to enable and retry (this will take a few minutes)? (y/N)?  y

Enabling service [cloudidentity.googleapis.com] on project [476118442898]...
Operation "operations/acat.p2-476118442898-2c8ba9c0-aedc-4e5c-8a63-40182b71d29c" finished successfully.
Created.
obriensystems commented 1 year ago

testing terraform I expected to have to add the two services to the bootstrap project cloudresourcemanager.googleapis.com cloudidentity.googleapis.com

Step #4 - "tf apply": │ Error: Error creating Group: googleapi: Error 403: Cloud Identity API has not been used in project 407485305437 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/cloudidentity.googleapis.com/overview?project=407485305437 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.

bootstrap = {
  projectServices = [
 ...   "cloudresourcemanager.googleapis.com", # for iam group creation
    "cloudidentity.googleapis.com" # for iam group creation

rerun bootstrap cloud build job

Step #4 - "tf apply": module.landing_zone_bootstrap.module.project.google_project_service.project_services["cloudidentity.googleapis.com"]: Creation complete after 21s [id=tzpe-tlz-tlz-de/cloudidentity.googleapis.com]

root_@cloudshell:~/lz-tls/_lz2/pbmm-on-gcp-onboarding (tzpe-tlz-tlz-de)$ gcloud services list | grep NAME
NAME: accesscontextmanager.googleapis.com
NAME: appengine.googleapis.com
NAME: artifactregistry.googleapis.com
NAME: cloudbilling.googleapis.com
NAME: cloudbuild.googleapis.com
NAME: cloudidentity.googleapis.com
NAME: cloudkms.googleapis.com
NAME: cloudresourcemanager.googleapis.com
NAME: compute.googleapis.com
NAME: containerregistry.googleapis.com
NAME: iam.googleapis.com
NAME: iamcredentials.googleapis.com
NAME: logging.googleapis.com
NAME: oslogin.googleapis.com
NAME: pubsub.googleapis.com
NAME: secretmanager.googleapis.com
NAME: serviceusage.googleapis.com
NAME: sourcerepo.googleapis.com
NAME: storage-api.googleapis.com

prod apply
3 - "tf plan": Terraform will perform the following actions:
Step #3 - "tf plan": 
Step #3 - "tf plan":   # module.group.google_cloud_identity_group.group will be created
Step #3 - "tf plan":   + resource "google_cloud_identity_group" "group" {
Step #3 - "tf plan":       + create_time          = (known after apply)
Step #3 - "tf plan":       + description          = "security group"
Step #3 - "tf plan":       + display_name         = "security"
Step #3 - "tf plan":       + id                   = (known after apply)
Step #3 - "tf plan":       + initial_group_config = "EMPTY"
Step #3 - "tf plan":       + labels               = {
Step #3 - "tf plan":           + "cloudidentity.googleapis.com/groups.discussion_forum" = ""
Step #3 - "tf plan":         }
Step #3 - "tf plan":       + name                 = (known after apply)
Step #3 - "tf plan":       + parent               = "customers/C02e6x9c7"
Step #3 - "tf plan":       + update_time          = (known after apply)
Step #3 - "tf plan": 
Step #3 - "tf plan":       + group_key {
Step #3 - "tf plan":           + id = "security@terraform.landing.systems"
Step #3 - "tf plan":         }
Step #3 - "tf plan":     }
Step #3 - "tf plan": 
Step #3 - "tf plan":   # module.group.google_cloud_identity_group_membership.managers["root@terraform.landing.systems"] will be created
Step #3 - "tf plan":   + resource "google_cloud_identity_group_membership" "managers" {
Step #3 - "tf plan":       + create_time = (known after apply)
Step #3 - "tf plan":       + group       = (known after apply)
Step #3 - "tf plan":       + id          = (known after apply)
Step #3 - "tf plan":       + name        = (known after apply)
Step #3 - "tf plan":       + type        = (known after apply)
Step #3 - "tf plan":       + update_time = (known after apply)
Step #3 - "tf plan": 
Step #3 - "tf plan":       + member_key {
Step #3 - "tf plan":           + id        = (known after apply)
Step #3 - "tf plan":           + namespace = (known after apply)
Step #3 - "tf plan":         }
Step #3 - "tf plan": 
Step #3 - "tf plan":       + preferred_member_key {
Step #3 - "tf plan":           + id = "root@terraform.landing.systems"
Step #3 - "tf plan":         }
Step #3 - "tf plan": 
Step #3 - "tf plan":       + roles {
Step #3 - "tf plan":           + name = "MANAGER"
Step #3 - "tf plan":         }
Step #3 - "tf plan":       + roles {
Step #3 - "tf plan":           + name = "MEMBER"
Step #3 - "tf plan":         }
Step #3 - "tf plan":     }
Step #3 - "tf plan": 
Step #3 - "tf plan":   # module.group.google_cloud_identity_group_membership.members["root@terraform.landing.systems"] will be created
Step #3 - "tf plan":   + resource "google_cloud_identity_group_membership" "members" {
Step #3 - "tf plan":       + create_time = (known after apply)
Step #3 - "tf plan":       + group       = (known after apply)
Step #3 - "tf plan":       + id          = (known after apply)
Step #3 - "tf plan":       + name        = (known after apply)
Step #3 - "tf plan":       + type        = (known after apply)
Step #3 - "tf plan":       + update_time = (known after apply)
Step #3 - "tf plan": 
Step #3 - "tf plan":       + member_key {
Step #3 - "tf plan":           + id        = (known after apply)
Step #3 - "tf plan":           + namespace = (known after apply)
Step #3 - "tf plan":         }
Step #3 - "tf plan": 
Step #3 - "tf plan":       + preferred_member_key {
Step #3 - "tf plan":           + id = "root@terraform.landing.systems"
Step #3 - "tf plan":         }
Step #3 - "tf plan": 
Step #3 - "tf plan":       + roles {
Step #3 - "tf plan":           + name = "MEMBER"
Step #3 - "tf plan":         }
Step #3 - "tf plan":     }
Step #3 - "tf plan": 
Step #3 - "tf plan":   # module.group.google_cloud_identity_group_membership.owners["root@terraform.landing.systems"] will be created
Step #3 - "tf plan":   + resource "google_cloud_identity_group_membership" "owners" {
Step #3 - "tf plan":       + create_time = (known after apply)
Step #3 - "tf plan":       + group       = (known after apply)
Step #3 - "tf plan":       + id          = (known after apply)
Step #3 - "tf plan":       + name        = (known after apply)
Step #3 - "tf plan":       + type        = (known after apply)
Step #3 - "tf plan":       + update_time = (known after apply)
Step #3 - "tf plan": 
Step #3 - "tf plan":       + member_key {
Step #3 - "tf plan":           + id        = (known after apply)
Step #3 - "tf plan":           + namespace = (known after apply)
Step #3 - "tf plan":         }
Step #3 - "tf plan": 
Step #3 - "tf plan":       + preferred_member_key {
Step #3 - "tf plan":           + id = "root@terraform.landing.systems"
Step #3 - "tf plan":         }
Step #3 - "tf plan": 
Step #3 - "tf plan":       + roles {
Step #3 - "tf plan":           + name = "MEMBER"
Step #3 - "tf plan":         }
Step #3 - "tf plan":       + roles {
Step #3 - "tf plan":           + name = "OWNER"
Step #3 - "tf plan":         }
Step #3 - "tf plan":     }

missing terraform service account permissions
4 - "tf apply": │ Error: Error creating Group: googleapi: Error 403: Error(2015): Permission denied for group resource 'security@terraform.landing.systems'.
Step #

add https://cloud.google.com/iam/docs/understanding-roles

Identity platform admin organization administrator

"roles/resourcemanager.organizationAdmin" "roles/identityplatform.admin"
Screenshot 2023-08-01 at 23 22 58

and add the Google Workspace Group Administrator Role https://cloud.google.com/identity/docs/how-to/setup#assigning_an_admin_role_to_the_service_account or make the tf sa an owner

owners = ["root...ems", "tfsa0131@tzpe-tlz-tlz-de.iam.gserviceaccount.com"]

does not work - need full https://workspaceupdates.googleblog.com/2020/08/use-service-accounts-google-groups-without-domain-wide-delegation.html

manually add tf sa to admin role

groups admin role

Screenshot 2023-08-01 at 23 46 39

assign service accounts

Screenshot 2023-08-01 at 23 47 13 Screenshot 2023-08-01 at 23 48 01 Screenshot 2023-08-01 at 23 48 38
Step #4 - "tf apply": │ Error: Error creating GroupMembership: googleapi: Error 409: The operation was aborted.
Step #4 - "tf apply": │ 
Step #4 - "tf apply": │   with module.group.google_cloud_identity_group_membership.owners["roo..stems"],
Step #4 - "tf apply": │   on .terraform/modules/group/main.tf line 51, in resource "google_cloud_identity_group_membership" "owners":
Step #4 - "tf apply": │   51: resource "google_cloud_identity_group_membership" "owners" {

for
module "group" {
  source  = "terraform-google-modules/group/google"
  version = "~> 0.6"

  id           = "security@terraform.landing.systems"
  display_name = "security"
  description  = "security group"
  domain       = "terraform.landing.systems"
  owners       = ["ro..systems", "tfsa0131@tzpe-tlz-tlz-de.iam.gserviceaccount.com"]
  managers     = ["ro..stems"]
  members      = ["ro..tems"]
}

retry - already existing - will full delete/recreate
Step #4 - "tf apply": │ Error: Error creating GroupMembership: googleapi: Error 409: Error(4003): Cannot create membership 'root@terraform.landing.systems' in 'groups/00tyjcwt1xepbql' because it already exists.
Screenshot 2023-08-01 at 23 56 51

destroy

Step #4 - "tf apply": module.net-host-prj.module.network["tlzprod-svpc"].module.subnets["prsubnet02"].google_compute_subnetwork.subnetwork: Modifying... [id=projects/tzpe-tlz-tlzprod-host4/regions/northamerica-northeast1/subnetworks/tzpecnr-prsubnet02-host4-snet]
Step #4 - "tf apply": module.group.google_cloud_identity_group_membership.members["root@terraform.landing.systems"]: Destroying... [id=groups/00tyjcwt1xepbql/memberships/101582649481786918348]
Step #4 - "tf apply": module.net-host-prj.module.network["tlzprod-svpc"].module.subnets["prsubnet02"].google_compute_subnetwork.subnetwork: Modifications complete after 1s [id=projects/tzpe-tlz-tlzprod-host4/regions/northamerica-northeast1/subnetworks/tzpecnr-prsubnet02-host4-snet]
Step #4 - "tf apply": module.group.google_cloud_identity_group_membership.members["root@terraform.landing.systems"]: Destruction complete after 1s
Step #4 - "tf apply": module.group.google_cloud_identity_group.group: Destroying... [id=groups/00tyjcwt1xepbql]
Step #4 - "tf apply": module.group.google_cloud_identity_group.group: Destruction complete after 6s
Screenshot 2023-08-02 at 00 01 07

recreate


Step #4 - "tf apply": module.group.google_cloud_identity_group.group: Creating...
Step #4 - "tf apply": module.net-host-prj.module.network["tlzprod-svpc"].module.subnets["prsubnet02"].google_compute_subnetwork.subnetwork: Modifying... [id=projects/tzpe-tlz-tlzprod-host4/regions/northamerica-northeast1/subnetworks/tzpecnr-prsubnet02-host4-snet]
Step #4 - "tf apply": module.net-host-prj.module.network["tlzprod-svpc"].module.subnets["prsubnet02"].google_compute_subnetwork.subnetwork: Modifications complete after 1s [id=projects/tzpe-tlz-tlzprod-host4/regions/northamerica-northeast1/subnetworks/tzpecnr-prsubnet02-host4-snet]
Step #4 - "tf apply": module.group.google_cloud_identity_group.group: Creation complete after 7s [id=groups/02zbgiuw25iqgfh]
Step #4 - "tf apply": module.group.google_cloud_identity_group_membership.members["root@terraform.landing.systems"]: Creating...
Step #4 - "tf apply": module.group.google_cloud_identity_group_membership.owners["root@terraform.landing.systems"]: Creating...
Step #4 - "tf apply": module.group.google_cloud_identity_group_membership.managers["root@terraform.landing.systems"]: Creating...
Step #4 - "tf apply": module.group.google_cloud_identity_group_membership.members["root@terraform.landing.systems"]: Creation complete after 1s [id=groups/02zbgiuw25iqgfh/memberships/101582649481786918348]

Step #4 - "tf apply": │ Error: Error creating GroupMembership: googleapi: Error 409: The operation was aborted.
Step #4 - "tf apply": │ 
Step #4 - "tf apply": │   with module.group.google_cloud_identity_group_membership.owners["root@terraform.landing.systems"],
Step #4 - "tf apply": │   on .terraform/modules/group/main.tf line 51, in resource "google_cloud_identity_group_membership" "owners":
Step #4 - "tf apply": │   51: resource "google_cloud_identity_group_membership" "owners" {
Step #4 - "tf apply": │ 
Step #4 - "tf apply": ╵
Step #4 - "tf apply": ╷
Step #4 - "tf apply": │ Error: Error creating GroupMembership: googleapi: Error 409: The operation was aborted.
Step #4 - "tf apply": │ 
Step #4 - "tf apply": │   with module.group.google_cloud_identity_group_membership.managers["root@terraform.landing.systems"],
Step #4 - "tf apply": │   on .terraform/modules/group/main.tf line 64, in resource "google_cloud_identity_group_membership" "managers":
Step #4 - "tf apply": │   64: resource "google_cloud_identity_group_membership" "managers" {
Step #4 - "tf apply": │ 
Step #4 - "tf apply": ╵

however the recreated group is good as of "members" - commenting owners and managers

Screenshot 2023-08-02 at 00 05 13

using

module "group" {
  source  = "terraform-google-modules/group/google"
  version = "~> 0.6"

  id           = "security@terraform.landing.systems"
  display_name = "security"
  description  = "security group"
  domain       = "terraform.landing.systems"
  #owners       = ["ro..tems"]#, "tfsa0131@tzpe-tlz-tlz-de.iam.gserviceaccount.com"]
  #managers     = ["ro..stems"]
  members      = ["ro..ms"]
}

we are good

Step #4 - "tf apply": module.net-host-prj.module.network["tlzprod-svpc"].module.subnets["prsubnet02"].google_compute_subnetwork.subnetwork: Modifying... [id=projects/tzpe-tlz-tlzprod-host4/regions/northamerica-northeast1/subnetworks/tzpecnr-prsubnet02-host4-snet]
Step #4 - "tf apply": module.group.google_cloud_identity_group.group: Creating...
Step #4 - "tf apply": module.net-host-prj.module.network["tlzprod-svpc"].module.subnets["prsubnet02"].google_compute_subnetwork.subnetwork: Modifications complete after 1s [id=projects/tzpe-tlz-tlzprod-host4/regions/northamerica-northeast1/subnetworks/tzpecnr-prsubnet02-host4-snet]
Step #4 - "tf apply": module.group.google_cloud_identity_group.group: Creation complete after 7s [id=groups/03as4poj0lu6dzm]
Step #4 - "tf apply": module.group.google_cloud_identity_group_membership.members["root@terraform.landing.systems"]: Creating...
Step #4 - "tf apply": module.group.google_cloud_identity_group_membership.members["root@terraform.landing.systems"]: Creation complete after 1s [id=groups/03as4poj0lu6dzm/memberships/101582649481786918348]

Step #4 - "tf apply": Apply complete! Resources: 2 added, 1 changed, 0 destroyed.
Screenshot 2023-08-02 at 00 15 30
obriensystems commented 1 year ago

move code from prod to common - expand identity lists and role assignments to the groups later

Screenshot 2023-08-02 at 10 54 56 Screenshot 2023-08-02 at 10 55 19

procedure to add the terraform service account as a groups admin in admin.google.com https://github.com/GoogleCloudPlatform/pbmm-on-gcp-onboarding/issues/271#issuecomment-1661425718

file list

        new file:   environments/common/iam-groups.auto.tfvars
        new file:   environments/common/iam-groups.tf
        modified:   environments/common/variables.tf
environments/bootstrap/bootstrap.sh
environments/bootstrap/bootstrap.auto.tfvars
obriensystems commented 1 year ago

Adding roles to groups

working - merging PR

obriensystems commented 1 year ago

adding plural groups note that adding multiple members will require recreation for now of the group - as it is mode authorative vs additive

Step #4 - "tf apply": │ Error: Error creating Group: googleapi: Error 409: Error(2018): Cannot create group 'security@terraform.landing.systems' because it already exists.

note recycling the group leaves orphaned IAM roles - no issue - they need a secondary pass

Screenshot 2023-08-02 at 12 15 29

raised https://github.com/GoogleCloudPlatform/pbmm-on-gcp-onboarding/issues/277

working

members = ["roo...ng.systems", "deve...ing.systems"]

Screenshot 2023-08-02 at 12 23 08 Screenshot 2023-08-02 at 12 23 25
obriensystems commented 1 year ago

multiple groups and roles ok - merging PR

Screenshot 2023-08-02 at 13 27 48 Screenshot 2023-08-02 at 13 28 16
obriensystems commented 1 year ago

rough pr

/**
 * Copyright 2023 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

# https://github.com/GoogleCloudPlatform/pbmm-on-gcp-onboarding/issues/271
# the terraform service account must be added in admin.google.com as a groups admin
# https://admin.google.com/ac/roles/58150197607268354
# move to common
module "group_opsadmin" {
  source  = "terraform-google-modules/group/google"
  version = "~> 0.6"

  id           = var.iam-group_opsadmin.id
  display_name = var.iam-group_opsadmin.display_name
  description  = var.iam-group_opsadmin.description
  domain       = var.iam-group_opsadmin.domain
  #owners       = var.iam-group_opsadmin.owners
  #managers     = var.iam-group_opsadmin.managers
  members      = var.iam-group_opsadmin.members
}

module "group_secadmin" {
  source  = "terraform-google-modules/group/google"
  version = "~> 0.6"

  id           = var.iam-group_secadmin.id
  display_name = var.iam-group_secadmin.display_name
  description  = var.iam-group_secadmin.description
  domain       = var.iam-group_secadmin.domain
  #owners       = var.iam-group_secadmin.owners
  #managers     = var.iam-group_secadmin.managers
  members      = var.iam-group_secadmin.members
}
module "group_telcoadmin" {
  source  = "terraform-google-modules/group/google"
  version = "~> 0.6"

  id           = var.iam-group_telcoadmin.id
  display_name = var.iam-group_telcoadmin.display_name
  description  = var.iam-group_telcoadmin.description
  domain       = var.iam-group_telcoadmin.domain
  #owners       = var.iam-group_telcoadmin.owners
  #managers     = var.iam-group_telcoadmin.managers
  members      = var.iam-group_telcoadmin.members
}
module "group_read" {
  source  = "terraform-google-modules/group/google"
  version = "~> 0.6"

  id           = var.iam-group_read.id
  display_name = var.iam-group_read.display_name
  description  = var.iam-group_read.description
  domain       = var.iam-group_read.domain
  #owners       = var.iam-group_read.owners
  #managers     = var.iam-group_read.managers
  members      = var.iam-group_read.members
}
module "group_billing" {
  source  = "terraform-google-modules/group/google"
  version = "~> 0.6"

  id           = var.iam-group_billing.id
  display_name = var.iam-group_billing.display_name
  description  = var.iam-group_billing.description
  domain       = var.iam-group_billing.domain
  #owners       = var.iam-group_billing.owners
  #managers     = var.iam-group_billing.managers
  members      = var.iam-group_billing.members
}
module "group_networkadmin" {
  source  = "terraform-google-modules/group/google"
  version = "~> 0.6"

  id           = var.iam-group_networkadmin.id
  display_name = var.iam-group_networkadmin.display_name
  description  = var.iam-group_networkadmin.description
  domain       = var.iam-group_networkadmin.domain
  #owners       = var.iam-group_networkadmin.owners
  #managers     = var.iam-group_networkadmin.managers
  members      = var.iam-group_networkadmin.members
}
module "iam-groups-roles" {
  source           = "../../modules/iam"
  #sa_create_assign = var.iam-groups.id #var.service_accounts
  #project_iam      = local.project_iam
  #folder_iam       = local.folder_iam
  organization_iam = var.organization_iam_group_opsadmin
  organization     = local.organization_config.org_id
  depends_on = [
    module.group_opsadmin#,
    #module.core-org-custom-roles,
    #module.core-folders
  ]
}

module "iam-groups-role_networkadmin" {
  source           = "../../modules/iam"
  #sa_create_assign = var.iam-groups.id #var.service_accounts
  #project_iam      = local.project_iam
  #folder_iam       = local.folder_iam
  organization_iam = var.organization_iam_group_networkadmin
  organization     = local.organization_config.org_id
  depends_on = [
    module.group_networkadmin#,
    #module.core-org-custom-roles,
    #module.core-folders
  ]
}

module "iam-groups-role_secadmin" {
  source           = "../../modules/iam"
  #sa_create_assign = var.iam-groups.id #var.service_accounts
  #project_iam      = local.project_iam
  #folder_iam       = local.folder_iam
  organization_iam = var.organization_iam_group_secadmin
  organization     = local.organization_config.org_id
  depends_on = [
    module.group_secadmin#,
    #module.core-org-custom-roles,
    #module.core-folders
  ]
}

module "iam-groups-role_telcoadmin" {
  source           = "../../modules/iam"
  #sa_create_assign = var.iam-groups.id #var.service_accounts
  #project_iam      = local.project_iam
  #folder_iam       = local.folder_iam
  organization_iam = var.organization_iam_group_telcoadmin
  organization     = local.organization_config.org_id
  depends_on = [
    module.group_telcoadmin#,
    #module.core-org-custom-roles,
    #module.core-folders
  ]
}

module "iam-groups-role_read" {
  source           = "../../modules/iam"
  #sa_create_assign = var.iam-groups.id #var.service_accounts
  #project_iam      = local.project_iam
  #folder_iam       = local.folder_iam
  organization_iam = var.organization_iam_group_read
  organization     = local.organization_config.org_id
  depends_on = [
    module.group_read#,
    #module.core-org-custom-roles,
    #module.core-folders
  ]
}

module "iam-groups-role_billing" {
  source           = "../../modules/iam"
  #sa_create_assign = var.iam-groups.id #var.service_accounts
  #project_iam      = local.project_iam
  #folder_iam       = local.folder_iam
  organization_iam = var.organization_iam_group_billing
  organization     = local.organization_config.org_id
  depends_on = [
    module.group_billing#,
    #module.core-org-custom-roles,
    #module.core-folders
  ]
}
/*
# https://github.com/GoogleCloudPlatform/pbmm-on-gcp-onboarding/issues/271
# the terraform service account must be added in admin.google.com as a groups admin
# https://admin.google.com/ac/roles/58150197607268354
# move to common
module "groups" {
  source  = "terraform-google-modules/group/google"
  version = "~> 0.6"

  id           = var.iam-groups.id
  display_name = var.iam-groups.display_name
  description  = var.iam-groups.description
  domain       = var.iam-groups.domain
  #owners       = var.iam-groups.owners
  #managers     = var.iam-groups.managers
  members      = var.iam-groups.members
}

module "iam-groups-roles" {
  source           = "../../modules/iam"
  #sa_create_assign = var.iam-groups.id #var.service_accounts
  #project_iam      = local.audit_project_iam
  #folder_iam       = local.folder_iam
  organization_iam = var.organization_iam_groups
  organization     = local.organization_config.org_id
  depends_on = [
    module.groups#,
    #module.core-org-custom-roles,
    #module.core-folders
  ]
}*/

# add roles to groups
# https://registry.terraform.io/modules/terraform-google-modules/iam/google/latest
# https://registry.terraform.io/modules/terraform-google-modules/iam/google/7.6.0/submodules/organizations_iam
/*module "organization-iam-bindings" {
  source        = "terraform-google-modules/iam/google//modules/organizations_iam"
  organizations = ["my-organization_one"]
  #mode          = "authoritative"
  mode          = "additive"

  bindings = {
    "roles/resourcemanager.organizationViewer" = [
      "serviceAccount:my-sa@my-project.iam.gserviceaccount.com",
      "group:my-group@my-org.com",
      "user:my-user@my-org.com",
    ]
    "roles/resourcemanager.projectDeleter" = [
      "serviceAccount:my-sa@my-project.iam.gserviceaccount.com",
      "group:my-group@my-org.com",
      "user:my-user@my-org.com",
    ]
  }
  conditional_bindings = [
    {
      role = "roles/editor"
      title = "expires_after_2019_12_31"
      description = "Expiring at midnight of 2019-12-31"
      expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")"
      members = ["user:my-user@my-org.com"]
    }
  ]
}*/

tfvars

/**
 * Copyright 2023 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
iam-groups = {
  id           = "security@terraform.landing.systems"
  display_name = "security"
  description  = "security group"
  domain       = "terraform.landing.systems"
  #owners       = ["root@terraform.landing.systems"]#, "tfsa0131@tzpe-tlz-tlz-de.iam.gserviceaccount.com"] # var.service_accounts
  #managers     = ["root@terraform.landing.systems"]
  members      = ["root@terraform.landing.systems", "developer@terraform.landing.systems"]
}*/

# when updating - recreate the entire group - authorative vs additive
iam-group_opsadmin = {
  id           = "opsadmin@terraform.landing.systems"
  display_name = "opsadmin"
  description  = "ops admin group"
  domain       = "terraform.landing.systems"
  #owners       = ["root@terraform.landing.systems"]#, "tfsa0131@tzpe-tlz-tlz-de.iam.gserviceaccount.com"] # var.service_accounts
  #managers     = ["root@terraform.landing.systems"]
  members      = ["root@terraform.landing.systems", "developer@terraform.landing.systems"]
}

iam-group_networkadmin = {
  id           = "networkadmin@terraform.landing.systems"
  display_name = "networkadmin"
  description  = "network admin group"
  domain       = "terraform.landing.systems"
  #owners       = ["root@terraform.landing.systems"]#, "tfsa0131@tzpe-tlz-tlz-de.iam.gserviceaccount.com"] # var.service_accounts
  #managers     = ["root@terraform.landing.systems"]
  members      = ["root@terraform.landing.systems", "developer@terraform.landing.systems"]
}

iam-group_telcoadmin = {
  id           = "telcoadmin@terraform.landing.systems"
  display_name = "telcoadmin"
  description  = "telco admin group"
  domain       = "terraform.landing.systems"
  #owners       = ["root@terraform.landing.systems"]#, "tfsa0131@tzpe-tlz-tlz-de.iam.gserviceaccount.com"] # var.service_accounts
  #managers     = ["root@terraform.landing.systems"]
  members      = ["root@terraform.landing.systems", "developer@terraform.landing.systems"]
}

iam-group_secadmin = {
  id           = "secadmin@terraform.landing.systems"
  display_name = "secadmin"
  description  = "security admin group"
  domain       = "terraform.landing.systems"
  #owners       = ["root@terraform.landing.systems"]#, "tfsa0131@tzpe-tlz-tlz-de.iam.gserviceaccount.com"] # var.service_accounts
  #managers     = ["root@terraform.landing.systems"]
  members      = ["root@terraform.landing.systems", "developer@terraform.landing.systems"]
}

iam-group_read = {
  id           = "read@terraform.landing.systems"
  display_name = "read"
  description  = "read group"
  domain       = "terraform.landing.systems"
  #owners       = ["root@terraform.landing.systems"]#, "tfsa0131@tzpe-tlz-tlz-de.iam.gserviceaccount.com"] # var.service_accounts
  #managers     = ["root@terraform.landing.systems"]
  members      = ["developer@terraform.landing.systems"]
}

iam-group_billing = {
  id           = "billing@terraform.landing.systems"
  display_name = "billing"
  description  = "billing group"
  domain       = "terraform.landing.systems"
  #owners       = ["root@terraform.landing.systems"]#, "tfsa0131@tzpe-tlz-tlz-de.iam.gserviceaccount.com"] # var.service_accounts
  #managers     = ["root@terraform.landing.systems"]
  members      = ["developer@terraform.landing.systems"]
}

organization_iam_groups = [
  {
    member       = "group:opsadmin@terraform.landing.systems" # REQUIRED EDIT. group:user@google.com
    organization = "131880894992" #Insert your Ord ID here, format ############
    roles = [
      "roles/viewer",
    ]
  }#,
   # {
   # member       = "group:prodbilling@terraform.landing.systems" # REQUIRED EDIT. group:user@google.com
   # organization = "131880894992" #Insert your Ord ID here, format ############
   # roles = [
   #   "roles/viewer",
   # ]
  #}
]

organization_iam_group_secadmin = [
  {
    member       = "group:secadmin@terraform.landing.systems" # REQUIRED EDIT. group:user@google.com
    organization = "131880894992" #Insert your Ord ID here, format ############
    roles = [
      "roles/viewer",
    ]
  }
]

organization_iam_group_networkadmin = [
  {
    member       = "group:networkadmin@terraform.landing.systems" # REQUIRED EDIT. group:user@google.com
    organization = "131880894992" #Insert your Ord ID here, format ############
    roles = [
      "roles/viewer",
    ]
  }
]

organization_iam_group_telcoadmin = [
  {
    member       = "group:telcoadmin@terraform.landing.systems" # REQUIRED EDIT. group:user@google.com
    organization = "131880894992" #Insert your Ord ID here, format ############
    roles = [
      "roles/viewer",
    ]
  }
]

organization_iam_group_read = [
  {
    member       = "group:read@terraform.landing.systems" # REQUIRED EDIT. group:user@google.com
    organization = "131880894992" #Insert your Ord ID here, format ############
    roles = [
      "roles/viewer",
    ]
  }
]

organization_iam_group_billing = [
  {
    member       = "group:billing@terraform.landing.systems" # REQUIRED EDIT. group:user@google.com
    organization = "131880894992" #Insert your Ord ID here, format ############
    roles = [
      "roles/viewer",
    ]
  }
]

organization_iam_group_opsadmin = [
  {
    member       = "group:opsadmin@terraform.landing.systems" # REQUIRED EDIT. group:user@google.com
    organization = "131880894992" #Insert your Ord ID here, format ############
    roles = [
      "roles/viewer",
    ]
  }
]
obriensystems commented 1 year ago

test results

Screenshot 2023-08-03 at 11 43 22
qingvincentyin commented 10 months ago

The top-level README should add instructions and screenshots about configuring Google Workspace for adding the SA to the Groups Admin role as per this comment.

It took me half a day to fight this bug. There's no clear instruction (or even clear diagnosis) on the general internet of how to solve this terraform error, until I found that excellent comment (with screenshots of Google Workspace admin console) in this thread.

What makes this bug harder to diagnose is that the gcloud CLI works without having to do the above in Google Workspace:

gcloud identity groups create test-group@example.com [--impersonate-service-account=tf-deploy@xxx.iam.gserviceaccount.com] ...

Even before I do anything in Google Workspace, the above CLI succeeded with or without --impersonate-service-account but terraform fails. So, it misled me to think that your terraform code didn't properly impersonate the SA. In retrospect, all I need is to configure Google Workspace as per your comment.

fmichaelobrien commented 10 months ago

Vincent, hi thank you for your comment. The repo is currently going through a retrofit where we are merging several customer oriented versions into the public repo - it is a work in progress over the last 2 weeks and will likely last a couple weeks more before we tag/version the repo

The terraform service account automation for group addition does have a manual workaround "for now" due to out of band GCP API constraints.

This change came in recently and requires documentation. The readme addition is in the evolving work items queue under https://github.com/GoogleCloudPlatform/pbmm-on-gcp-onboarding/issues/308

which references the currently documented "rough" but not ready for read me version https://github.com/GoogleCloudPlatform/pbmm-on-gcp-onboarding/issues/271#issuecomment-1661425718

I myself ran into this issue and found the workaround as well and did a quick writeup but due to ongoing prioritization triage the change is still pending - will send you and update when we can get the readme change in.

thank you /michael

fmichaelobrien commented 4 months ago

20240406: Closing issue during retrofit/rebase of this TEF V1 based/modified repo to TEF V4 standards This issue may participate in the LZ refactor after rebase Query on all issues related to the older V1 version via the tag https://github.com/GoogleCloudPlatform/pbmm-on-gcp-onboarding/labels/2024-pre-tef-v4