251 lines
7.7 KiB
HCL
251 lines
7.7 KiB
HCL
/**
|
|
* Copyright 2024 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.
|
|
*/
|
|
|
|
# tfdoc:file:description Organization-level IAM.
|
|
|
|
locals {
|
|
# reassemble logical bindings into the formats expected by the module
|
|
_iam_bindings = merge(
|
|
local.iam_domain_bindings,
|
|
local.iam_sa_bindings,
|
|
local.iam_user_bootstrap_bindings,
|
|
{
|
|
for k, v in local.iam_principal_bindings : k => {
|
|
authoritative = []
|
|
additive = v.additive
|
|
}
|
|
}
|
|
)
|
|
_iam_bindings_auth = flatten([
|
|
for member, data in local._iam_bindings : [
|
|
for role in data.authoritative : {
|
|
member = member
|
|
role = role
|
|
}
|
|
]
|
|
])
|
|
_iam_bindings_add = flatten([
|
|
for member, data in local._iam_bindings : [
|
|
for role in data.additive : {
|
|
member = member
|
|
role = role
|
|
}
|
|
]
|
|
])
|
|
drs_domains = concat(
|
|
var.organization.customer_id == null ? [] : [var.organization.customer_id],
|
|
var.org_policies_config.constraints.allowed_policy_member_domains
|
|
)
|
|
drs_tag_name = "${var.organization.id}/${var.org_policies_config.tag_name}"
|
|
fast_custom_roles = [
|
|
"organization_admin_viewer",
|
|
"organization_iam_admin",
|
|
"service_project_network_admin",
|
|
"storage_viewer",
|
|
"tag_viewer",
|
|
"tenant_network_admin",
|
|
]
|
|
# intermediate values before we merge in what comes from the checklist
|
|
_iam_principals = {
|
|
for k, v in local.iam_principal_bindings : k => v.authoritative
|
|
}
|
|
_iam = merge(
|
|
{
|
|
for r in local.iam_delete_roles : r => []
|
|
},
|
|
{
|
|
for b in local._iam_bindings_auth : b.role => b.member...
|
|
}
|
|
)
|
|
_iam_bindings_additive = {
|
|
for b in local._iam_bindings_add : "${b.role}-${b.member}" => {
|
|
member = b.member
|
|
role = b.role
|
|
}
|
|
}
|
|
# final values combining all sources
|
|
iam_principals = {
|
|
for k, v in local._iam_principals : k => distinct(concat(
|
|
v,
|
|
try(local.checklist.iam_principals[k], [])
|
|
))
|
|
}
|
|
iam = {
|
|
for k, v in local._iam : k => distinct(concat(
|
|
v,
|
|
try(local.checklist.iam[k].authoritative, [])
|
|
))
|
|
}
|
|
iam_bindings_additive = merge(
|
|
local._iam_bindings_additive,
|
|
{
|
|
for k, v in try(local.checklist.iam_bindings, {}) :
|
|
v.key => v if lookup(local._iam_bindings_additive, v.key, null) == null
|
|
}
|
|
)
|
|
# compute authoritative and additive roles for use by add-ons (checklist, etc.)
|
|
iam_roles_authoritative = distinct(concat(
|
|
flatten(values(local._iam_principals)),
|
|
keys(local._iam)
|
|
))
|
|
iam_roles_additive = distinct([
|
|
for k, v in local._iam_bindings_additive : v.role
|
|
])
|
|
}
|
|
|
|
# TODO: add a check block to ensure our custom roles exist in the factory files
|
|
|
|
# import org policy constraints enabled by default in new orgs since February 2024
|
|
import {
|
|
for_each = (
|
|
!var.org_policies_config.import_defaults || var.bootstrap_user != null
|
|
? toset([])
|
|
: toset([
|
|
"compute.requireOsLogin",
|
|
"compute.skipDefaultNetworkCreation",
|
|
"compute.vmExternalIpAccess",
|
|
"iam.allowedPolicyMemberDomains",
|
|
"iam.automaticIamGrantsForDefaultServiceAccounts",
|
|
"iam.disableServiceAccountKeyCreation",
|
|
"iam.disableServiceAccountKeyUpload",
|
|
"sql.restrictAuthorizedNetworks",
|
|
"sql.restrictPublicIp",
|
|
"storage.uniformBucketLevelAccess",
|
|
])
|
|
)
|
|
id = "organizations/${var.organization.id}/policies/${each.key}"
|
|
to = module.organization.google_org_policy_policy.default[each.key]
|
|
}
|
|
|
|
module "organization" {
|
|
source = "../../../modules/organization"
|
|
organization_id = "organizations/${var.organization.id}"
|
|
# human (groups) IAM bindings
|
|
iam_by_principals = {
|
|
for k, v in local.iam_principals :
|
|
k => distinct(concat(v, lookup(var.iam_by_principals, k, [])))
|
|
}
|
|
# machine (service accounts) IAM bindings
|
|
iam = merge(
|
|
{
|
|
for k, v in local.iam : k => distinct(concat(v, lookup(var.iam, k, [])))
|
|
},
|
|
{
|
|
for k, v in var.iam : k => v if lookup(local.iam, k, null) == null
|
|
}
|
|
)
|
|
# additive bindings, used for roles co-managed by different stages
|
|
iam_bindings_additive = merge(
|
|
local.iam_bindings_additive,
|
|
var.iam_bindings_additive
|
|
)
|
|
# delegated role grant for resource manager service account
|
|
iam_bindings = merge(
|
|
{
|
|
organization_iam_admin_conditional = {
|
|
members = [module.automation-tf-resman-sa.iam_email]
|
|
role = module.organization.custom_role_id["organization_iam_admin"]
|
|
condition = {
|
|
expression = format(
|
|
"api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
|
|
join(",", formatlist("'%s'", [
|
|
"roles/accesscontextmanager.policyAdmin",
|
|
"roles/compute.orgFirewallPolicyAdmin",
|
|
"roles/compute.xpnAdmin",
|
|
"roles/orgpolicy.policyAdmin",
|
|
"roles/orgpolicy.policyViewer",
|
|
"roles/resourcemanager.organizationViewer",
|
|
module.organization.custom_role_id["tenant_network_admin"]
|
|
]))
|
|
)
|
|
title = "automation_sa_delegated_grants"
|
|
description = "Automation service account delegated grants."
|
|
}
|
|
}
|
|
},
|
|
local.billing_mode != "org" ? {} : {
|
|
organization_billing_conditional = {
|
|
members = [module.automation-tf-resman-sa.iam_email]
|
|
role = module.organization.custom_role_id["organization_iam_admin"]
|
|
condition = {
|
|
expression = format(
|
|
"api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
|
|
join(",", formatlist("'%s'", [
|
|
"roles/billing.admin",
|
|
"roles/billing.costsManager",
|
|
"roles/billing.user",
|
|
]))
|
|
)
|
|
title = "automation_sa_delegated_grants"
|
|
description = "Automation service account delegated grants."
|
|
}
|
|
}
|
|
}
|
|
)
|
|
custom_roles = var.custom_roles
|
|
factories_config = {
|
|
custom_roles = var.factories_config.custom_roles
|
|
org_policies = (
|
|
var.bootstrap_user != null ? null : var.factories_config.org_policy
|
|
)
|
|
}
|
|
logging_sinks = {
|
|
for name, attrs in var.log_sinks : name => {
|
|
bq_partitioned_table = attrs.type == "bigquery"
|
|
destination = local.log_sink_destinations[name].id
|
|
filter = attrs.filter
|
|
type = attrs.type
|
|
}
|
|
}
|
|
org_policies = var.bootstrap_user != null ? {} : {
|
|
"iam.allowedPolicyMemberDomains" = {
|
|
rules = [
|
|
{
|
|
allow = { values = local.drs_domains }
|
|
condition = {
|
|
expression = (
|
|
"!resource.matchTag('${local.drs_tag_name}', 'allowed-policy-member-domains-all')"
|
|
)
|
|
}
|
|
},
|
|
{
|
|
allow = { all = true }
|
|
condition = {
|
|
expression = (
|
|
"resource.matchTag('${local.drs_tag_name}', 'allowed-policy-member-domains-all')"
|
|
)
|
|
title = "allow-all"
|
|
}
|
|
},
|
|
]
|
|
}
|
|
# "gcp.resourceLocations" = {}
|
|
# "iam.workloadIdentityPoolProviders" = {}
|
|
}
|
|
tags = {
|
|
(var.org_policies_config.tag_name) = {
|
|
description = "Organization policy conditions."
|
|
iam = {}
|
|
values = merge(
|
|
{
|
|
allowed-policy-member-domains-all = {}
|
|
},
|
|
var.org_policies_config.tag_values
|
|
)
|
|
}
|
|
}
|
|
}
|