Rationalize project factory context interpolations for automation service accounts (#2959)
* use different keys for automation service accounts * inventory * improve error handling on automation buckets
This commit is contained in:
committed by
GitHub
parent
b50e8a16dc
commit
717f89dc00
@@ -196,8 +196,8 @@ Interpolations leverage contexts from two separate sources: an internal set for
|
||||
|
||||
The following table lists the available context interpolations. External contexts are passed in via the `factories_config.contexts` variable. IAM principals are interpolated in all IAM attributes except `iam_by_principal`. First two columns show for which attribute of which resource context is interpolated. `external contexts` column show in which map passed as `var.factories_config.context` key will be looked up.
|
||||
|
||||
* Internally created folders creates keys under `${folder_name_1}[/${folder_name_2}/${folder_name_3}]`
|
||||
* IAM principals are resolved within context of managed project or use `${project}/${service_account}` to refer service account from other projects managed by the same project factory instance.
|
||||
- Internally created folders creates keys under `${folder_name_1}[/${folder_name_2}/${folder_name_3}]`
|
||||
- IAM principals are resolved within context of managed project or use `${project}/${service_account}` to refer service account from other projects managed by the same project factory instance.
|
||||
|
||||
| resource | attribute | external contexts | internal contexts |
|
||||
|---------------------|-----------------|---------------------|------------------------------------|
|
||||
@@ -400,9 +400,9 @@ services:
|
||||
- storage.googleapis.com
|
||||
iam:
|
||||
"roles/owner":
|
||||
- rw
|
||||
- automation/rw
|
||||
"roles/viewer":
|
||||
- ro
|
||||
- automation/ro
|
||||
shared_vpc_host_config:
|
||||
enabled: true
|
||||
automation:
|
||||
@@ -416,12 +416,12 @@ automation:
|
||||
description: Team B app 0 Terraform state bucket.
|
||||
iam:
|
||||
roles/storage.objectCreator:
|
||||
- rw
|
||||
- automation/rw
|
||||
roles/storage.objectViewer:
|
||||
- gcp-devops
|
||||
- group:team-b-admins@example.org
|
||||
- rw
|
||||
- ro
|
||||
- automation/rw
|
||||
- automation/ro
|
||||
|
||||
# tftest-file id=7 path=data/projects/dev-tb-app0-0.yaml schema=project.schema.json
|
||||
```
|
||||
|
||||
@@ -35,7 +35,7 @@ locals {
|
||||
]
|
||||
])
|
||||
}
|
||||
output "foo" { value = local.automation_buckets }
|
||||
|
||||
module "automation-bucket" {
|
||||
source = "../gcs"
|
||||
for_each = local.automation_buckets
|
||||
@@ -58,9 +58,20 @@ module "automation-bucket" {
|
||||
for k, v in lookup(each.value, "iam_bindings", {}) : k => merge(v, {
|
||||
members = [
|
||||
for vv in v.members : try(
|
||||
# rw (infer local project and automation prefix)
|
||||
module.automation-service-accounts["${each.key}/automation/${vv}"].iam_email,
|
||||
# automation/rw or sa (infer local project)
|
||||
module.automation-service-accounts["${each.key}/${vv}"].iam_email,
|
||||
# project/automation/rw project/sa
|
||||
var.factories_config.context.iam_principals[vv],
|
||||
vv
|
||||
# fully specified principal
|
||||
vv,
|
||||
# passthrough + error handling using tonumber until Terraform gets fail/raise function
|
||||
(
|
||||
strcontains(vv, ":")
|
||||
? vv
|
||||
: tonumber("[Error] Invalid member: '${vv}' in automation bucket '${each.key}'")
|
||||
)
|
||||
)
|
||||
]
|
||||
})
|
||||
@@ -94,7 +105,7 @@ module "automation-bucket" {
|
||||
module "automation-service-accounts" {
|
||||
source = "../iam-service-account"
|
||||
for_each = {
|
||||
for k in local.automation_sa : "${k.project}/${k.name}" => k
|
||||
for k in local.automation_sa : "${k.project}/automation/${k.name}" => k
|
||||
}
|
||||
# we cannot use interpolation here as we would get a cycle
|
||||
# from the IAM dependency in the outputs of the main project
|
||||
@@ -107,6 +118,7 @@ module "automation-service-accounts" {
|
||||
"display_name",
|
||||
"Service account ${each.value.name} for ${each.value.project}."
|
||||
)
|
||||
# TODO: also support short form for service accounts in this project
|
||||
iam = {
|
||||
for k, v in lookup(each.value, "iam", {}) : k => [
|
||||
for vv in v : lookup(
|
||||
|
||||
@@ -106,16 +106,22 @@ module "projects-iam" {
|
||||
iam = {
|
||||
for k, v in lookup(each.value, "iam", {}) : k => [
|
||||
for vv in v : try(
|
||||
# project service accounts
|
||||
# project service accounts (sa)
|
||||
module.service-accounts["${each.key}/${vv}"].iam_email,
|
||||
# automation service account
|
||||
# automation service account (rw)
|
||||
local.context.iam_principals["${each.key}/automation/${vv}"],
|
||||
# automation service account (automation/rw)
|
||||
local.context.iam_principals["${each.key}/${vv}"],
|
||||
# other projects service accounts
|
||||
# other projects service accounts (project/sa)
|
||||
module.service-accounts[vv].iam_email,
|
||||
# other automation service account
|
||||
# other automation service account (project/automation/rw)
|
||||
local.context.iam_principals[vv],
|
||||
# passthrough + error handling using tonumber until Terraform gets fail/raise function
|
||||
strcontains(vv, ":") ? vv : tonumber("[Error] Invalid member: '${vv}' in project '${each.key}'")
|
||||
(
|
||||
strcontains(vv, ":")
|
||||
? vv
|
||||
: tonumber("[Error] Invalid member: '${vv}' in project '${each.key}'")
|
||||
)
|
||||
)
|
||||
]
|
||||
}
|
||||
@@ -123,16 +129,22 @@ module "projects-iam" {
|
||||
for k, v in lookup(each.value, "iam_bindings", {}) : k => merge(v, {
|
||||
members = [
|
||||
for vv in v.members : try(
|
||||
# project service accounts
|
||||
# project service accounts (sa)
|
||||
module.service-accounts["${each.key}/${vv}"].iam_email,
|
||||
# automation service account
|
||||
# automation service account (rw)
|
||||
local.context.iam_principals["${each.key}/automation/${vv}"],
|
||||
# automation service account (automation/rw)
|
||||
local.context.iam_principals["${each.key}/${vv}"],
|
||||
# other projects service accounts
|
||||
# other projects service accounts (project/sa)
|
||||
module.service-accounts[vv].iam_email,
|
||||
# other automation service account
|
||||
# other automation service account (project/automation/rw)
|
||||
local.context.iam_principals[vv],
|
||||
# passthrough + error handling using tonumber until Terraform gets fail/raise function
|
||||
strcontains(vv, ":") ? vv : tonumber("[Error] Invalid member: '${vv}' in project '${each.key}'")
|
||||
(
|
||||
strcontains(vv, ":")
|
||||
? vv
|
||||
: tonumber("[Error] Invalid member: '${vv}' in project '${each.key}'")
|
||||
)
|
||||
)
|
||||
]
|
||||
})
|
||||
@@ -140,16 +152,22 @@ module "projects-iam" {
|
||||
iam_bindings_additive = {
|
||||
for k, v in lookup(each.value, "iam_bindings_additive", {}) : k => merge(v, {
|
||||
member = try(
|
||||
# project service accounts
|
||||
# project service accounts (sa)
|
||||
module.service-accounts["${each.key}/${v.member}"].iam_email,
|
||||
# automation service account
|
||||
# automation service account (rw)
|
||||
local.context.iam_principals["${each.key}/automation/${v.member}"],
|
||||
# automation service account (automation/rw)
|
||||
local.context.iam_principals["${each.key}/${v.member}"],
|
||||
# other projects service accounts
|
||||
# other projects service accounts (project/sa)
|
||||
module.service-accounts[v.member].iam_email,
|
||||
# other automation service account
|
||||
# other automation service account (project/automation/rw)
|
||||
local.context.iam_principals[v.member],
|
||||
# passthrough + error handling using tonumber until Terraform gets fail/raise function
|
||||
strcontains(v.member, ":") ? v.member : tonumber("[Error] Invalid member: '${v.member}' in project '${each.key}'")
|
||||
(
|
||||
strcontains(v.member, ":")
|
||||
? v.member
|
||||
: tonumber("[Error] Invalid member: '${v.member}' in project '${each.key}'")
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -164,32 +182,38 @@ module "projects-iam" {
|
||||
try(each.value.shared_vpc_service_config.host_project, null) == null
|
||||
? null
|
||||
: merge(each.value.shared_vpc_service_config, {
|
||||
host_project = lookup(
|
||||
var.factories_config.context.vpc_host_projects,
|
||||
each.value.shared_vpc_service_config.host_project,
|
||||
host_project = try(
|
||||
var.factories_config.context.vpc_host_projects[each.value.shared_vpc_service_config.host_project],
|
||||
module.projects[each.value.shared_vpc_service_config.host_project].project_id,
|
||||
each.value.shared_vpc_service_config.host_project
|
||||
)
|
||||
network_users = [
|
||||
for v in try(each.value.shared_vpc_service_config.network_users, []) :
|
||||
for vv in try(each.value.shared_vpc_service_config.network_users, []) :
|
||||
try(
|
||||
# project service accounts
|
||||
module.service-accounts["${each.key}/${v}"].iam_email,
|
||||
# automation service account
|
||||
local.context.iam_principals["${each.key}/${v}"],
|
||||
# other projects service accounts
|
||||
module.service-accounts[v].iam_email,
|
||||
# other automation service account
|
||||
local.context.iam_principals[v],
|
||||
# project service accounts (sa)
|
||||
module.service-accounts["${each.key}/${vv}"].iam_email,
|
||||
# automation service account (rw)
|
||||
local.context.iam_principals["${each.key}/automation/${vv}"],
|
||||
# automation service account (automation/rw)
|
||||
local.context.iam_principals["${each.key}/${vv}"],
|
||||
# other projects service accounts (project/sa)
|
||||
module.service-accounts[vv].iam_email,
|
||||
# other automation service account (project/automation/rw)
|
||||
local.context.iam_principals[vv],
|
||||
# passthrough + error handling using tonumber until Terraform gets fail/raise function
|
||||
strcontains(v, ":") ? v : tonumber("[Error] Invalid member: '${v}' in project '${each.key}'")
|
||||
(
|
||||
strcontains(vv, ":")
|
||||
? vv
|
||||
: tonumber("[Error] Invalid member: '${vv}' in project '${each.key}'")
|
||||
)
|
||||
)
|
||||
]
|
||||
# TODO: network subnet users
|
||||
})
|
||||
)
|
||||
# add service agents config, so Service Agents can be referred in the IAM grants
|
||||
service_agents_config = {
|
||||
grant_default_roles = false # Default roles are granted in module.project
|
||||
# default roles are granted in module.project
|
||||
grant_default_roles = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,16 +229,22 @@ module "buckets" {
|
||||
iam = {
|
||||
for k, v in each.value.iam : k => [
|
||||
for vv in v : try(
|
||||
# project service accounts
|
||||
# project service accounts (sa)
|
||||
module.service-accounts["${each.value.project}/${vv}"].iam_email,
|
||||
# automation service account
|
||||
# automation service account (rw)
|
||||
local.context.iam_principals["${each.value.project}/automation/${vv}"],
|
||||
# automation service account (automation/rw)
|
||||
local.context.iam_principals["${each.value.project}/${vv}"],
|
||||
# other projects service accounts
|
||||
# other projects service accounts (project/sa)
|
||||
module.service-accounts[vv].iam_email,
|
||||
# other automation service account
|
||||
# other automation service account (project/automation/rw)
|
||||
local.context.iam_principals[vv],
|
||||
# passthrough + error handling using tonumber until Terraform gets fail/raise function
|
||||
strcontains(vv, ":") ? vv : tonumber("[Error] Invalid member: '${vv}' for bucket '${each.key}' in project '${each.value.project}'")
|
||||
(
|
||||
strcontains(vv, ":")
|
||||
? vv
|
||||
: tonumber("[Error] Invalid member: '${vv}' in project '${each.value.project}'")
|
||||
)
|
||||
)
|
||||
]
|
||||
}
|
||||
@@ -222,16 +252,22 @@ module "buckets" {
|
||||
for k, v in each.value.iam_bindings : k => merge(v, {
|
||||
members = [
|
||||
for vv in v.members : try(
|
||||
# project service accounts
|
||||
# project service accounts (sa)
|
||||
module.service-accounts["${each.value.project}/${vv}"].iam_email,
|
||||
# automation service account
|
||||
# automation service account (rw)
|
||||
local.context.iam_principals["${each.value.project}/automation/${vv}"],
|
||||
# automation service account (automation/rw)
|
||||
local.context.iam_principals["${each.value.project}/${vv}"],
|
||||
# other projects service accounts
|
||||
# other projects service accounts (project/sa)
|
||||
module.service-accounts[vv].iam_email,
|
||||
# other automation service account
|
||||
# other automation service account (project/automation/rw)
|
||||
local.context.iam_principals[vv],
|
||||
# passthrough + error handling using tonumber until Terraform gets fail/raise function
|
||||
strcontains(vv, ":") ? vv : tonumber("[Error] Invalid member: '${vv}' for bucket '${each.key}' in project '${each.value.project}'")
|
||||
(
|
||||
strcontains(vv, ":")
|
||||
? vv
|
||||
: tonumber("[Error] Invalid member: '${vv}' in project '${each.value.project}'")
|
||||
)
|
||||
)
|
||||
]
|
||||
})
|
||||
@@ -239,16 +275,22 @@ module "buckets" {
|
||||
iam_bindings_additive = {
|
||||
for k, v in each.value.iam_bindings_additive : k => merge(v, {
|
||||
member = try(
|
||||
# project service accounts
|
||||
# project service accounts (sa)
|
||||
module.service-accounts["${each.value.project}/${v.member}"].iam_email,
|
||||
# automation service account
|
||||
# automation service account (rw)
|
||||
local.context.iam_principals["${each.value.project}/automation/${v.member}"],
|
||||
# automation service account (automation/rw)
|
||||
local.context.iam_principals["${each.value.project}/${v.member}"],
|
||||
# other projects service accounts
|
||||
# other projects service accounts (project/sa)
|
||||
module.service-accounts[v.member].iam_email,
|
||||
# other automation service account
|
||||
# other automation service account (project/automation/rw)
|
||||
local.context.iam_principals[v.member],
|
||||
# passthrough + error handling using tonumber until Terraform gets fail/raise function
|
||||
strcontains(v.member, ":") ? v.member : tonumber("[Error] Invalid member: '${v.member}' for bucket '${each.key}' in project '${each.value.project}'")
|
||||
(
|
||||
strcontains(v.member, ":")
|
||||
? v.member
|
||||
: tonumber("[Error] Invalid member: '${v.member}' in project '${each.value.project}'")
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user