* Allow creation of dynamic tags * Extend project factory and related modules to support dynamic values * Extend folder and organization modules * project and organization readme * Simplify dynamic tag support and remove unnecessary restrictions • Schemas & Validations: Removed the restriction that forbade combining IAM fields with allowed_values_regex on tags. Updated validations in project and organization modules, and simplified all relevant JSON schemas. • Module Tag Bindings: Simplified the tag_value assignment in folder , project , gcs , bigquery-dataset , and kms modules by removing the defensive can(regex(...)) check and calling templatestring directly. • Outputs: Removed the tags_dynamic output from project and organization modules, as the same information is now available in tag_keys . • Project Factory: Updated tag_vars_projects in projects.tf to use the native namespaced_name attribute and filtered manually for dynamic tags. * fix(organization, project): fix linting and tests for dynamic tag support - Align allowed_values_regex and description extraction in _tags_merged locals to use lookup() for consistency with other fields. - Fix spacing in project context variable (alphabetical ordering). - Update organization tags test to include the new cost_center tag key with allowed_values_regex. - Update project tags test to include the new cost_center tag key and reflect the resolved allowed_values_regex on environment. * refactor(gcs): refine tag bindings and fix context test - Add _tag_bindings local to pre-resolve context references, enabling templatestring to receive a direct map reference (required by Terraform). - Use var.context.tag_vars instead of the non-existent local.ctx.tag_vars. - Fix HCL syntax in context.tfvars (escaped inner quotes). - Update context test inventory to reflect 3 tag bindings including a dynamic value resolved via templatestring. * refactor: align modules with tag binding context pattern - Add _tag_bindings local + templatestring dance to cloud-run-v2, compute-vm, folder, kms modules (bigquery-dataset already had it) - Exclude tag_vars from local.ctx in cloud-run-v2, compute-vm, folder, kms, project modules (bigquery-dataset already had it) - Add tag_vars to context variable in cloud-run-v2, compute-vm modules (others already had it) - Update all context tests with dynamic tag binding values using var.context.tag_vars * docs: add module-level tftest.yaml test instructions to GEMINI.md * docs: regenerate READMEs after tag-regex alignment - Regenerate variable tables in 7 module READMEs to reflect line number shifts from prior tag-regex changes - Add tag_vars exclusion to gcs ctx local - Fix whitespace alignment in iam-service-account and project-factory tag_vars blocks - Update tftest resource counts for organization and project - Remove tags_dynamic from organization/project output tables * fix(project-factory): update test inventory for tag_bindings module split - Move tag binding address from folder-2 to folder-2-iam in test inventory (tag_bindings moved from creation to IAM modules) - Update module instance count from 34 to 35 - Regenerate README tables after terraform fmt line shifts - Apply terraform fmt to variables.tf * refactor(project-factory): remove unnecessary depends_on from folder-iam modules Folder IAM modules depend on their own folder creation modules, not on module.projects. The explicit depends_on was leftover from an earlier design. * FAST stages * Address review comments. - FAST Stages: - Added tag_keys to output-files.tf in 0-org-setup to pass org tags via tfvars. - Sorted tag_keys and tag_values in output-files.tf. - Updated project-factory, networking, and security stages to use tag_keys. - Filtered tag_keys for dynamic tags only. - Modules: - Excluded tag_vars from local.ctx in iam-service-account and organization. - Simplified tag_value in iam-service-account. - Tests: - Updated test inventories for 0-org-setup and project-factory. * Fix tf format * Fix tfdoc * docs: add ADR for templatestring vars convention and update status of base path ADR * More tfdoc * Update schemas * Use endswith in context loop * Address review * Update FAST readmes * Update last modules * Terraform fmt * Revert alloydb * Fix whitespace --------- Co-authored-by: Ludovico Magnocavallo <ludo@qix.it>
Certificate Authority Service (CAS)
The module allows you to create one or more CAs and an optional CA pool.
Examples
Basic CA infrastructure
This is enough to create a test CA pool and a self-signed root CA.
module "cas" {
source = "./fabric/modules/certificate-authority-service"
project_id = var.project_id
location = "europe-west1"
ca_pool_config = {
create_pool = {
name = "test-ca"
}
}
}
# tftest modules=1 resources=2 inventory=basic.yaml
Create custom CAs
You can create multiple, custom CAs.
module "cas" {
source = "./fabric/modules/certificate-authority-service"
project_id = var.project_id
location = "europe-west1"
ca_pool_config = {
create_pool = {
name = "test-ca"
}
}
ca_configs = {
root_ca_1 = {
key_usage = {
client_auth = true
server_auth = true
}
}
root_ca_2 = {
subject = {
common_name = "test2.example.com"
organization = "Example"
}
}
}
}
# tftest modules=1 resources=3 inventory=custom_cas.yaml
Reference an existing CA pool
module "cas" {
source = "./fabric/modules/certificate-authority-service"
project_id = var.project_id
location = "europe-west1"
ca_pool_config = {
use_pool = {
id = var.ca_pool_id
}
}
}
# tftest modules=1 resources=1 inventory=existing_ca.yaml
IAM
You can assign authoritative and addittive IAM roles to identities on the CA pool, using the usual fabric interface (iam, iam_bindings, iam_binding_addittive, iam_by_principals).
module "cas" {
source = "./fabric/modules/certificate-authority-service"
project_id = var.project_id
location = "europe-west1"
ca_pool_config = {
create_pool = {
name = "test-ca"
}
}
iam = {
"roles/privateca.certificateManager" = [
var.service_account.iam_email
]
}
iam_bindings_additive = {
cert-manager = {
member = "group:${var.group_email}"
role = "roles/privateca.certificateManager"
}
}
}
# tftest modules=1 resources=4 inventory=iam.yaml
Variables
| name | description | type | required | default |
|---|---|---|---|---|
| ca_pool_config | The CA pool config. Either use_pool or create_pool need to be used. Use pool takes precedence if both are defined. | object({…}) |
✓ | |
| location | The location of the CAs. | string |
✓ | |
| project_id | Project id. | string |
✓ | |
| ca_configs | The CA configurations. | map(object({…})) |
{…} |
|
| context | Context-specific interpolations. | object({…}) |
{} |
|
| iam | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) |
{} |
|
| iam_bindings | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…})) |
{} |
|
| iam_bindings_additive | Individual additive IAM bindings. Keys are arbitrary. | map(object({…})) |
{} |
|
| iam_by_principals | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the iam variable. |
map(list(string)) |
{} |
Outputs
| name | description | sensitive |
|---|---|---|
| ca_chains | The CA chains in PEM format. | |
| ca_ids | The CA ids. | |
| ca_pool | The CA pool. | |
| ca_pool_id | The CA pool id. | |
| cas | The CAs. |