Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add main project factory service account #2353

Merged
merged 2 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions fast/stages/1-resman/README.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions fast/stages/1-resman/billing.tf
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ locals {
local.branch_optional_sa_lists.gke-prod,
local.branch_optional_sa_lists.gcve-dev,
local.branch_optional_sa_lists.gcve-prod,
local.branch_optional_sa_lists.pf,
local.branch_optional_sa_lists.pf-dev,
local.branch_optional_sa_lists.pf-prod,
)
Expand Down
4 changes: 4 additions & 0 deletions fast/stages/1-resman/branch-networking.tf
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,15 @@ module "branch-network-prod-folder" {
local.branch_optional_sa_lists.dp-prod,
local.branch_optional_sa_lists.gke-prod,
local.branch_optional_sa_lists.gcve-prod,
local.branch_optional_sa_lists.pf,
local.branch_optional_sa_lists.pf-prod,
)
# read-only (plan) automation service accounts
"roles/compute.networkViewer" = concat(
local.branch_optional_r_sa_lists.dp-prod,
local.branch_optional_r_sa_lists.gke-prod,
local.branch_optional_r_sa_lists.gcve-prod,
local.branch_optional_r_sa_lists.pf,
local.branch_optional_r_sa_lists.pf-prod,
)
(local.custom_roles.gcve_network_admin) = local.branch_optional_sa_lists.gcve-prod
Expand All @@ -97,13 +99,15 @@ module "branch-network-dev-folder" {
local.branch_optional_sa_lists.dp-dev,
local.branch_optional_sa_lists.gke-dev,
local.branch_optional_sa_lists.gcve-dev,
local.branch_optional_sa_lists.pf,
local.branch_optional_sa_lists.pf-dev,
)
# read-only (plan) automation service accounts
"roles/compute.networkViewer" = concat(
local.branch_optional_r_sa_lists.dp-dev,
local.branch_optional_r_sa_lists.gke-dev,
local.branch_optional_r_sa_lists.gcve-dev,
local.branch_optional_r_sa_lists.pf,
local.branch_optional_r_sa_lists.pf-dev,
)
(local.custom_roles.gcve_network_admin) = local.branch_optional_sa_lists.gcve-dev
Expand Down
55 changes: 55 additions & 0 deletions fast/stages/1-resman/branch-project-factory.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,26 @@

# automation service accounts

module "branch-pf-sa" {
source = "../../../modules/iam-service-account"
count = var.fast_features.project_factory ? 1 : 0
project_id = var.automation.project_id
name = "resman-pf-0"
display_name = "Terraform project factory main service account."
prefix = var.prefix
iam = {
"roles/iam.serviceAccountTokenCreator" = compact([
try(module.branch-pf-sa-cicd[0].iam_email, null)
])
}
iam_project_roles = {
(var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"]
}
iam_storage_roles = {
(var.automation.outputs_bucket) = ["roles/storage.objectAdmin"]
}
}

module "branch-pf-dev-sa" {
source = "../../../modules/iam-service-account"
count = var.fast_features.project_factory ? 1 : 0
Expand Down Expand Up @@ -60,6 +80,26 @@ module "branch-pf-prod-sa" {

# automation read-only service accounts

module "branch-pf-r-sa" {
source = "../../../modules/iam-service-account"
count = var.fast_features.project_factory ? 1 : 0
project_id = var.automation.project_id
name = "resman-pf-0r"
display_name = "Terraform project factory main service account (read-only)."
prefix = var.prefix
iam = {
"roles/iam.serviceAccountTokenCreator" = compact([
try(module.branch-pf-r-sa-cicd[0].iam_email, null)
])
}
iam_project_roles = {
(var.automation.project_id) = ["roles/serviceusage.serviceUsageConsumer"]
}
iam_storage_roles = {
(var.automation.outputs_bucket) = [var.custom_roles["storage_viewer"]]
}
}

module "branch-pf-dev-r-sa" {
source = "../../../modules/iam-service-account"
count = var.fast_features.project_factory ? 1 : 0
Expand Down Expand Up @@ -102,6 +142,21 @@ module "branch-pf-prod-r-sa" {

# automation buckets

module "branch-pf-gcs" {
source = "../../../modules/gcs"
count = var.fast_features.project_factory ? 1 : 0
project_id = var.automation.project_id
name = "resman-pf-0"
prefix = var.prefix
location = var.locations.gcs
storage_class = local.gcs_storage_class
versioning = true
iam = {
"roles/storage.objectAdmin" = [module.branch-pf-sa[0].iam_email]
"roles/storage.objectViewer" = [module.branch-pf-r-sa[0].iam_email]
}
}

module "branch-pf-dev-gcs" {
source = "../../../modules/gcs"
count = var.fast_features.project_factory ? 1 : 0
Expand Down
63 changes: 63 additions & 0 deletions fast/stages/1-resman/cicd-project-factory.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,41 @@

# read-write (apply) SAs used by CI/CD workflows to impersonate automation SAs

module "branch-pf-sa-cicd" {
source = "../../../modules/iam-service-account"
for_each = (
try(local.cicd_repositories.project_factory.name, null) != null
? { 0 = local.cicd_repositories.project_factory }
: {}
)
project_id = var.automation.project_id
name = "pf-resman-pf-1"
display_name = "Terraform CI/CD project factory main service account."
prefix = var.prefix
iam = {
"roles/iam.workloadIdentityUser" = [
each.value.branch == null
? format(
local.identity_providers[each.value.identity_provider].principal_repo,
var.automation.federated_identity_pool,
each.value.name
)
: format(
local.identity_providers[each.value.identity_provider].principal_branch,
var.automation.federated_identity_pool,
each.value.name,
each.value.branch
)
]
}
iam_project_roles = {
(var.automation.project_id) = ["roles/logging.logWriter"]
}
iam_storage_roles = {
(var.automation.outputs_bucket) = ["roles/storage.objectViewer"]
}
}

module "branch-pf-dev-sa-cicd" {
source = "../../../modules/iam-service-account"
for_each = (
Expand Down Expand Up @@ -90,6 +125,34 @@ module "branch-pf-prod-sa-cicd" {

# read-only (plan) SAs used by CI/CD workflows to impersonate automation SAs

module "branch-pf-r-sa-cicd" {
source = "../../../modules/iam-service-account"
for_each = (
try(local.cicd_repositories.project_factory.name, null) != null
? { 0 = local.cicd_repositories.project_factory }
: {}
)
project_id = var.automation.project_id
name = "resman-pf-1r"
display_name = "Terraform CI/CD project factory main service account (read-only)."
prefix = var.prefix
iam = {
"roles/iam.workloadIdentityUser" = [
format(
local.identity_providers[each.value.identity_provider].principal_repo,
var.automation.federated_identity_pool,
each.value.name
)
]
}
iam_project_roles = {
(var.automation.project_id) = ["roles/logging.logWriter"]
}
iam_storage_roles = {
(var.automation.outputs_bucket) = ["roles/storage.objectViewer"]
}
}

module "branch-pf-dev-r-sa-cicd" {
source = "../../../modules/iam-service-account"
for_each = (
Expand Down
21 changes: 20 additions & 1 deletion fast/stages/1-resman/iam.tf
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ locals {
},
# optional billing roles for project factory
local.billing_mode != "org" || !var.fast_features.project_factory ? {} : {
sa_pf_billing = {
member = module.branch-pf-sa[0].iam_email
role = "roles/billing.user"
}
sa_pf_costs_manager = {
member = module.branch-pf-sa[0].iam_email
role = "roles/billing.costsManager"
}
sa_pf_dev_billing = {
member = module.branch-pf-dev-sa[0].iam_email
role = "roles/billing.user"
Expand All @@ -90,8 +98,19 @@ locals {
}
},
# scoped org policy admin grants for project factory
# TODO: exclude security and networking
# TODO: change to use context and environment tags, and tag bindings in stage 2s
!var.fast_features.project_factory || var.root_node != null ? {} : {
sa_pf_conditional_org_policy = {
member = module.branch-pf-sa[0].iam_email
role = "roles/orgpolicy.policyAdmin"
condition = {
title = "org_policy_tag_pf_scoped"
description = "Org policy tag scoped grant for project factory main."
expression = <<-END
resource.matchTag('${local.tag_root}/${var.tag_names.context}', 'project-factory')
END
}
}
sa_pf_dev_conditional_org_policy = {
member = module.branch-pf-dev-sa[0].iam_email
role = "roles/orgpolicy.policyAdmin"
Expand Down
2 changes: 2 additions & 0 deletions fast/stages/1-resman/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ locals {
gcve-prod = compact([try(module.branch-gcve-prod-sa[0].iam_email, "")])
gke-dev = compact([try(module.branch-gke-dev-sa[0].iam_email, "")])
gke-prod = compact([try(module.branch-gke-prod-sa[0].iam_email, "")])
pf = compact([try(module.branch-pf-sa[0].iam_email, "")])
pf-dev = compact([try(module.branch-pf-dev-sa[0].iam_email, "")])
pf-prod = compact([try(module.branch-pf-prod-sa[0].iam_email, "")])
}
Expand All @@ -39,6 +40,7 @@ locals {
gcve-prod = compact([try(module.branch-gcve-prod-r-sa[0].iam_email, "")])
gke-dev = compact([try(module.branch-gke-dev-r-sa[0].iam_email, "")])
gke-prod = compact([try(module.branch-gke-prod-r-sa[0].iam_email, "")])
pf = compact([try(module.branch-pf-r-sa[0].iam_email, "")])
pf-dev = compact([try(module.branch-pf-dev-r-sa[0].iam_email, "")])
pf-prod = compact([try(module.branch-pf-prod-r-sa[0].iam_email, "")])
}
Expand Down
3 changes: 3 additions & 0 deletions fast/stages/1-resman/organization.tf
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ module "organization" {
networking = {
iam = try(local.tags.context.values.networking.iam, {})
}
project-factory = {
iam = try(local.tags.context.values.project-factory.iam, {})
}
sandbox = {
iam = try(local.tags.context.values.sandbox.iam, {})
}
Expand Down
37 changes: 33 additions & 4 deletions fast/stages/1-resman/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,17 @@ locals {
}
tf_var_files = local.cicd_workflow_var_files.stage_2
}
project_factory = {
service_accounts = {
apply = try(module.branch-pf-sa-cicd[0].email, null)
plan = try(module.branch-pf-r-sa-cicd[0].email, null)
}
tf_providers_files = {
apply = "3-project-factory-providers.tf"
plan = "3-project-factory-r-providers.tf"
}
tf_var_files = local.cicd_workflow_var_files.stage_3
}
project_factory_dev = {
service_accounts = {
apply = try(module.branch-pf-dev-sa-cicd[0].email, null)
Expand Down Expand Up @@ -276,28 +287,40 @@ locals {
})
},
!var.fast_features.project_factory ? {} : {
"3-project-factory" = templatefile(local._tpl_providers, {
backend_extra = null
bucket = module.branch-pf-gcs[0].name
name = "project-factory"
sa = module.branch-pf-sa[0].email
})
"3-project-factory-r" = templatefile(local._tpl_providers, {
backend_extra = null
bucket = module.branch-pf-gcs[0].name
name = "project-factory"
sa = module.branch-pf-r-sa[0].email
})
"3-project-factory-dev" = templatefile(local._tpl_providers, {
backend_extra = null
bucket = module.branch-pf-dev-gcs[0].name
name = "team-dev"
name = "project-factory-dev"
sa = module.branch-pf-dev-sa[0].email
})
"3-project-factory-dev-r" = templatefile(local._tpl_providers, {
backend_extra = null
bucket = module.branch-pf-dev-gcs[0].name
name = "team-dev"
name = "project-factory-dev"
sa = module.branch-pf-dev-r-sa[0].email
})
"3-project-factory-prod" = templatefile(local._tpl_providers, {
backend_extra = null
bucket = module.branch-pf-prod-gcs[0].name
name = "team-prod"
name = "project-factory-prod"
sa = module.branch-pf-prod-sa[0].email
})
"3-project-factory-prod-r" = templatefile(local._tpl_providers, {
backend_extra = null
bucket = module.branch-pf-prod-gcs[0].name
name = "team-prod"
name = "project-factory-prod"
sa = module.branch-pf-prod-r-sa[0].email
})
},
Expand Down Expand Up @@ -326,6 +349,8 @@ locals {
gke-prod-r = try(module.branch-gke-prod-r-sa[0].email, null)
networking = module.branch-network-sa.email
networking-r = module.branch-network-r-sa.email
project-factory = try(module.branch-pf-sa[0].email, null)
project-factory-r = try(module.branch-pf-r-sa[0].email, null)
project-factory-dev = try(module.branch-pf-dev-sa[0].email, null)
project-factory-dev-r = try(module.branch-pf-dev-r-sa[0].email, null)
project-factory-prod = try(module.branch-pf-prod-sa[0].email, null)
Expand Down Expand Up @@ -442,6 +467,10 @@ output "project_factories" {
bucket = module.branch-pf-dev-gcs[0].name
sa = module.branch-pf-dev-sa[0].email
}
main = {
bucket = module.branch-pf-gcs[0].name
sa = module.branch-pf-sa[0].email
}
prod = {
bucket = module.branch-pf-prod-gcs[0].name
sa = module.branch-pf-prod-sa[0].email
Expand Down
6 changes: 6 additions & 0 deletions fast/stages/1-resman/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ variable "cicd_repositories" {
branch = optional(string)
identity_provider = optional(string)
}))
project_factory = optional(object({
name = string
type = string
branch = optional(string)
identity_provider = optional(string)
}))
project_factory_dev = optional(object({
name = string
type = string
Expand Down
2 changes: 1 addition & 1 deletion fast/stages/2-networking-a-simple/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS
| [outputs_location](variables.tf#L92) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | <code>string</code> | | <code>null</code> | |
| [psa_ranges](variables.tf#L98) | IP ranges used for Private Service Access (CloudSQL, etc.). | <code title="object&#40;&#123;&#10; dev &#61; optional&#40;list&#40;object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; export_routes &#61; optional&#40;bool, false&#41;&#10; import_routes &#61; optional&#40;bool, false&#41;&#10; peered_domains &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10; &#125;&#41;&#41;, &#91;&#93;&#41;&#10; prod &#61; optional&#40;list&#40;object&#40;&#123;&#10; ranges &#61; map&#40;string&#41;&#10; export_routes &#61; optional&#40;bool, false&#41;&#10; import_routes &#61; optional&#40;bool, false&#41;&#10; peered_domains &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10; &#125;&#41;&#41;, &#91;&#93;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> | |
| [regions](variables.tf#L118) | Region definitions. | <code title="object&#40;&#123;&#10; primary &#61; string&#10; secondary &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; primary &#61; &#34;europe-west1&#34;&#10; secondary &#61; &#34;europe-west4&#34;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [service_accounts](variables-fast.tf#L89) | Automation service accounts in name => email format. | <code title="object&#40;&#123;&#10; data-platform-dev &#61; string&#10; data-platform-prod &#61; string&#10; gke-dev &#61; string&#10; gke-prod &#61; string&#10; project-factory-dev &#61; string&#10; project-factory-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>1-resman</code> |
| [service_accounts](variables-fast.tf#L89) | Automation service accounts in name => email format. | <code title="object&#40;&#123;&#10; data-platform-dev &#61; string&#10; data-platform-prod &#61; string&#10; gke-dev &#61; string&#10; gke-prod &#61; string&#10; project-factory &#61; string&#10; project-factory-dev &#61; string&#10; project-factory-prod &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | <code>1-resman</code> |
| [spoke_configs](variables.tf#L130) | Spoke connectivity configurations. | <code title="object&#40;&#123;&#10; peering_configs &#61; optional&#40;object&#40;&#123;&#10; dev &#61; optional&#40;object&#40;&#123;&#10; export &#61; optional&#40;bool, true&#41;&#10; import &#61; optional&#40;bool, true&#41;&#10; public_export &#61; optional&#40;bool&#41;&#10; public_import &#61; optional&#40;bool&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; prod &#61; optional&#40;object&#40;&#123;&#10; export &#61; optional&#40;bool, true&#41;&#10; import &#61; optional&#40;bool, true&#41;&#10; public_export &#61; optional&#40;bool&#41;&#10; public_import &#61; optional&#40;bool&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; &#125;&#41;&#41;&#10; vpn_configs &#61; optional&#40;object&#40;&#123;&#10; dev &#61; optional&#40;object&#40;&#123;&#10; asn &#61; optional&#40;number, 65501&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; landing &#61; optional&#40;object&#40;&#123;&#10; asn &#61; optional&#40;number, 65500&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; prod &#61; optional&#40;object&#40;&#123;&#10; asn &#61; optional&#40;number, 65502&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; peering_configs &#61; &#123;&#125;&#10;&#125;">&#123;&#8230;&#125;</code> | |
| [vpn_onprem_primary_config](variables.tf#L180) | VPN gateway configuration for onprem interconnection in the primary region. | <code title="object&#40;&#123;&#10; peer_external_gateways &#61; map&#40;object&#40;&#123;&#10; redundancy_type &#61; string&#10; interfaces &#61; list&#40;string&#41;&#10; &#125;&#41;&#41;&#10; router_config &#61; object&#40;&#123;&#10; create &#61; optional&#40;bool, true&#41;&#10; asn &#61; number&#10; name &#61; optional&#40;string&#41;&#10; keepalive &#61; optional&#40;number&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; tunnels &#61; map&#40;object&#40;&#123;&#10; bgp_peer &#61; object&#40;&#123;&#10; address &#61; string&#10; asn &#61; number&#10; route_priority &#61; optional&#40;number, 1000&#41;&#10; custom_advertise &#61; optional&#40;object&#40;&#123;&#10; all_subnets &#61; bool&#10; all_vpc_subnets &#61; bool&#10; all_peer_vpc_subnets &#61; bool&#10; ip_ranges &#61; map&#40;string&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;&#10; bgp_session_range &#61; string&#10; ike_version &#61; optional&#40;number, 2&#41;&#10; peer_external_gateway_interface &#61; optional&#40;number&#41;&#10; peer_gateway &#61; optional&#40;string, &#34;default&#34;&#41;&#10; router &#61; optional&#40;string&#41;&#10; shared_secret &#61; optional&#40;string&#41;&#10; vpn_gateway_interface &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | |

Expand Down
Loading
Loading