Skip to content

Commit bf337bd

Browse files
committed
feat: change 'gitlab_group_id' and 'gitlab_project_id' variables to 'gitlab_group_ids' and 'gitlab_project_ids' allowing for multiple GitLab groups or projects configuration
1 parent c2acb40 commit bf337bd

File tree

10 files changed

+122
-60
lines changed

10 files changed

+122
-60
lines changed

CHANGELOG.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,46 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
88

99
## [Unreleased]
1010

11+
## [0.5.0] - 2025-05-30
12+
13+
[Compare with previous version](https://github.com/sparkfabrik/terraform-google-gcp-gitlab-wif/compare/0.4.0...0.5.0)
14+
15+
### :warning: Breaking change
16+
17+
The variables `gitlab_group_id` and `gitlab_project_id` have been renamed to `gitlab_group_ids` and `gitlab_project_ids` and the type has been changed from `string` to `list(string)`. This allows for multiple group and project IDs to be specified.
18+
19+
You can update your configuration simply by changing the variable names and wrapping the existing values in a list, like this:
20+
21+
**From:**
22+
23+
```hcl
24+
module "example" {
25+
source = "github.com/sparkfabrik/terraform-google-gcp-gitlab-wif?ref=main"
26+
version = ">= 0.1.0"
27+
28+
name = "My Workload Identity Federation"
29+
gcp_project_id = "awesome-gcp-project"
30+
gitlab_project_id = 42
31+
}
32+
```
33+
34+
**To:**
35+
36+
```hcl
37+
module "example" {
38+
source = "github.com/sparkfabrik/terraform-google-gcp-gitlab-wif?ref=main"
39+
version = ">= 0.1.0"
40+
41+
name = "My Workload Identity Federation"
42+
gcp_project_id = "awesome-gcp-project"
43+
gitlab_project_ids = [42]
44+
}
45+
```
46+
47+
### Changed
48+
49+
- Change the variables `gitlab_group_id` and `gitlab_project_id` to `gitlab_group_ids` and `gitlab_project_ids`, allowing for multiple group and project IDs to be specified.
50+
1151
## [0.4.0] - 2025-05-29
1252

1353
[Compare with previous version](https://github.com/sparkfabrik/terraform-google-gcp-gitlab-wif/compare/0.3.1...0.4.0)

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ You can refer to the official [GitLab documentation](https://docs.gitlab.com/ci/
3434
| <a name="input_gitlab_gcp_wif_project_id_variable_name"></a> [gitlab\_gcp\_wif\_project\_id\_variable\_name](#input\_gitlab\_gcp\_wif\_project\_id\_variable\_name) | The name of the GitLab variable to store the GCP project ID for WIF. | `string` | `"GCP_WIF_PROJECT_ID"` | no |
3535
| <a name="input_gitlab_gcp_wif_provider_variable_name"></a> [gitlab\_gcp\_wif\_provider\_variable\_name](#input\_gitlab\_gcp\_wif\_provider\_variable\_name) | The name of the GitLab variable to store the GCP WIF provider name. | `string` | `"GCP_WIF_PROVIDER"` | no |
3636
| <a name="input_gitlab_gcp_wif_service_account_email_variable_name"></a> [gitlab\_gcp\_wif\_service\_account\_email\_variable\_name](#input\_gitlab\_gcp\_wif\_service\_account\_email\_variable\_name) | The name of the GitLab variable to store the GCP WIF service account email. | `string` | `"GCP_WIF_SERVICE_ACCOUNT_EMAIL"` | no |
37-
| <a name="input_gitlab_group_id"></a> [gitlab\_group\_id](#input\_gitlab\_group\_id) | The GitLab group ID to allow access from. Use this for group-level access. | `number` | `0` | no |
37+
| <a name="input_gitlab_group_ids"></a> [gitlab\_group\_ids](#input\_gitlab\_group\_ids) | The GitLab group IDs to allow access from. Use this for group-level access. | `list(number)` | `[]` | no |
3838
| <a name="input_gitlab_instance_url"></a> [gitlab\_instance\_url](#input\_gitlab\_instance\_url) | The URL of your GitLab instance. | `string` | `"https://gitlab.com"` | no |
39-
| <a name="input_gitlab_project_id"></a> [gitlab\_project\_id](#input\_gitlab\_project\_id) | The GitLab project ID to allow access from. Use this for project-level access. | `number` | `0` | no |
39+
| <a name="input_gitlab_project_ids"></a> [gitlab\_project\_ids](#input\_gitlab\_project\_ids) | The GitLab project IDs to allow access from. Use this for project-level access. | `list(number)` | `[]` | no |
4040
| <a name="input_gitlab_variables_additional"></a> [gitlab\_variables\_additional](#input\_gitlab\_variables\_additional) | Additional GitLab variables to create. This should be a map where the key is the variable name and the value is an object containing the variable properties. This allows you to define custom variables for project or group where the module is applied. | <pre>map(object({<br/> value = string<br/> protected = optional(bool, false)<br/> masked = optional(bool, false)<br/> description = optional(string, "Managed by {{MANAGER_NAME}}.")<br/> }))</pre> | `{}` | no |
4141
| <a name="input_gitlab_variables_description"></a> [gitlab\_variables\_description](#input\_gitlab\_variables\_description) | The description for the GitLab variables created by this module. You can use `{{MANAGER_NAME}}` to include the name of the 'manager' defined in `gitlab_variables_description_manager_name`. | `string` | `"Managed by {{MANAGER_NAME}}."` | no |
4242
| <a name="input_gitlab_variables_description_manager_name"></a> [gitlab\_variables\_description\_manager\_name](#input\_gitlab\_variables\_description\_manager\_name) | The name of the manager to include in the GitLab variable description. | `string` | `"terraform-google-gcp-gitlab-wif module"` | no |
@@ -49,7 +49,7 @@ You can refer to the official [GitLab documentation](https://docs.gitlab.com/ci/
4949
| Name | Description |
5050
|------|-------------|
5151
| <a name="output_gitlab_variables"></a> [gitlab\_variables](#output\_gitlab\_variables) | The GitLab variables created by this module. |
52-
| <a name="output_principal_set"></a> [principal\_set](#output\_principal\_set) | The principal set string used for IAM bindings. |
52+
| <a name="output_principal_set"></a> [principal\_set](#output\_principal\_set) | The principal sets string used for IAM bindings. |
5353
| <a name="output_secret_created"></a> [secret\_created](#output\_secret\_created) | The names and IDs of the secrets created by this module. |
5454
| <a name="output_secret_ids"></a> [secret\_ids](#output\_secret\_ids) | Map of original secret names to their Secret Manager secret IDs |
5555
| <a name="output_secret_names"></a> [secret\_names](#output\_secret\_names) | Map of original secret names to their formatted names |

examples/main.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module "example" {
77

88
name = var.name
99
gcp_project_id = var.gcp_project_id
10-
gitlab_project_id = var.gitlab_project_id
10+
gitlab_project_ids = var.gitlab_project_ids
1111
gitlab_instance_url = var.gitlab_instance_url
1212
secret_gcp_project_id = var.secret_gcp_project_id
1313
secret_names = var.secret_names

examples/test.tfvars

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "MyAwesomeWif"
22
gcp_project_id = "my-gcp-project-id"
3-
gitlab_project_id = 42
3+
gitlab_project_id = [42]
44
gitlab_instance_url = "https://my.gitlab.com"
55
secret_gcp_project_id = "my-gcp-secret-project-id"
66
secret_names = [

examples/variables.tf

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ variable "gcp_project_id" {
1010
}
1111

1212
# GitLab variables
13-
variable "gitlab_project_id" {
14-
description = "The GitLab project ID to allow access from. Use this for project-level access."
15-
type = string
13+
variable "gitlab_project_ids" {
14+
description = "The GitLab project IDs to allow access from. Use this for project-level access."
15+
type = list(number)
16+
default = []
1617
}
1718

1819
variable "gitlab_instance_url" {

gitlab.tf

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# GitLab group and project variables for Workload Identity Federation
22
# Group variables if `var.gitlab_group_id` is provided
33
resource "gitlab_group_variable" "gcp_wif_project_id" {
4-
count = local.is_gitlab_group_level ? 1 : 0
4+
for_each = local.is_gitlab_group_level ? toset(var.gitlab_group_ids) : []
55

6-
group = var.gitlab_group_id
6+
group = each.value
77
key = var.gitlab_gcp_wif_project_id_variable_name
88
value = data.google_project.project.number
99
description = local.gitlab_variables_description
@@ -12,9 +12,9 @@ resource "gitlab_group_variable" "gcp_wif_project_id" {
1212
}
1313

1414
resource "gitlab_group_variable" "gcp_wif_pool" {
15-
count = local.is_gitlab_group_level ? 1 : 0
15+
for_each = local.is_gitlab_group_level ? toset(var.gitlab_group_ids) : []
1616

17-
group = var.gitlab_group_id
17+
group = each.value
1818
key = var.gitlab_gcp_wif_pool_variable_name
1919
value = google_iam_workload_identity_pool.this.workload_identity_pool_id
2020
description = local.gitlab_variables_description
@@ -23,9 +23,9 @@ resource "gitlab_group_variable" "gcp_wif_pool" {
2323
}
2424

2525
resource "gitlab_group_variable" "gcp_wif_provider" {
26-
count = local.is_gitlab_group_level ? 1 : 0
26+
for_each = local.is_gitlab_group_level ? toset(var.gitlab_group_ids) : []
2727

28-
group = var.gitlab_group_id
28+
group = each.value
2929
key = var.gitlab_gcp_wif_provider_variable_name
3030
value = google_iam_workload_identity_pool_provider.this.workload_identity_pool_provider_id
3131
description = local.gitlab_variables_description
@@ -34,9 +34,9 @@ resource "gitlab_group_variable" "gcp_wif_provider" {
3434
}
3535

3636
resource "gitlab_group_variable" "gcp_wif_service_account_email" {
37-
count = local.is_gitlab_group_level ? 1 : 0
37+
for_each = local.is_gitlab_group_level ? toset(var.gitlab_group_ids) : []
3838

39-
group = var.gitlab_group_id
39+
group = each.value
4040
key = var.gitlab_gcp_wif_service_account_email_variable_name
4141
value = local.sa_email
4242
description = local.gitlab_variables_description
@@ -47,8 +47,8 @@ resource "gitlab_group_variable" "gcp_wif_service_account_email" {
4747
resource "gitlab_group_variable" "gitlab_variables_additional" {
4848
for_each = local.is_gitlab_group_level ? local.gitlab_variables_additional_final : {}
4949

50-
group = var.gitlab_group_id
51-
key = each.key
50+
group = each.value.gitlab_resource_id
51+
key = each.value.key
5252
value = each.value.value
5353
description = each.value.description
5454
protected = each.value.protected
@@ -57,9 +57,9 @@ resource "gitlab_group_variable" "gitlab_variables_additional" {
5757

5858
# Project variables if `var.gitlab_project_id` is provided
5959
resource "gitlab_project_variable" "gcp_wif_project_id" {
60-
count = local.is_gitlab_project_level ? 1 : 0
60+
for_each = local.is_gitlab_project_level ? toset(var.gitlab_project_ids) : []
6161

62-
project = var.gitlab_project_id
62+
project = each.value
6363
key = var.gitlab_gcp_wif_project_id_variable_name
6464
value = data.google_project.project.number
6565
description = local.gitlab_variables_description
@@ -68,9 +68,9 @@ resource "gitlab_project_variable" "gcp_wif_project_id" {
6868
}
6969

7070
resource "gitlab_project_variable" "gcp_wif_pool" {
71-
count = local.is_gitlab_project_level ? 1 : 0
71+
for_each = local.is_gitlab_project_level ? toset(var.gitlab_project_ids) : []
7272

73-
project = var.gitlab_project_id
73+
project = each.value
7474
key = var.gitlab_gcp_wif_pool_variable_name
7575
value = google_iam_workload_identity_pool.this.workload_identity_pool_id
7676
description = local.gitlab_variables_description
@@ -79,9 +79,9 @@ resource "gitlab_project_variable" "gcp_wif_pool" {
7979
}
8080

8181
resource "gitlab_project_variable" "gcp_wif_provider" {
82-
count = local.is_gitlab_project_level ? 1 : 0
82+
for_each = local.is_gitlab_project_level ? toset(var.gitlab_project_ids) : []
8383

84-
project = var.gitlab_project_id
84+
project = each.value
8585
key = var.gitlab_gcp_wif_provider_variable_name
8686
value = google_iam_workload_identity_pool_provider.this.workload_identity_pool_provider_id
8787
description = local.gitlab_variables_description
@@ -90,9 +90,9 @@ resource "gitlab_project_variable" "gcp_wif_provider" {
9090
}
9191

9292
resource "gitlab_project_variable" "gcp_wif_service_account_email" {
93-
count = local.is_gitlab_project_level ? 1 : 0
93+
for_each = local.is_gitlab_project_level ? toset(var.gitlab_project_ids) : []
9494

95-
project = var.gitlab_project_id
95+
project = each.value
9696
key = var.gitlab_gcp_wif_service_account_email_variable_name
9797
value = local.sa_email
9898
description = local.gitlab_variables_description
@@ -103,8 +103,8 @@ resource "gitlab_project_variable" "gcp_wif_service_account_email" {
103103
resource "gitlab_project_variable" "gitlab_variables_additional" {
104104
for_each = local.is_gitlab_project_level ? local.gitlab_variables_additional_final : {}
105105

106-
project = var.gitlab_project_id
107-
key = each.key
106+
project = each.value.gitlab_resource_id
107+
key = each.value.key
108108
value = each.value.value
109109
description = each.value.description
110110
protected = each.value.protected

locals.tf

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
locals {
22
resource_name_suffix = "${var.name}-${random_id.suffix.hex}"
3-
is_gitlab_group_level = var.gitlab_group_id > 0
4-
is_gitlab_project_level = var.gitlab_project_id > 0
5-
attribute_condition = local.is_gitlab_project_level ? "assertion.project_id==\"${var.gitlab_project_id}\"" : "assertion.namespace_id==\"${var.gitlab_group_id}\""
6-
principal_subject = local.is_gitlab_project_level ? "attribute.project_id/${var.gitlab_project_id}" : "attribute.namespace_id/${var.gitlab_group_id}"
7-
principal_set = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.this.name}/${local.principal_subject}"
3+
is_gitlab_group_level = length(var.gitlab_group_ids) > 0
4+
is_gitlab_project_level = length(var.gitlab_project_ids) > 0
5+
attribute_conditions = local.is_gitlab_project_level ? {
6+
for id in var.gitlab_project_ids : "procject-${id}" => "assertion.project_id==\"${id}\""
7+
} : {
8+
for id in var.gitlab_group_ids : "group-${id}" => "assertion.namespace_id==\"${id}\""
9+
}
10+
principal_subjects = local.is_gitlab_project_level ? {
11+
for id in var.gitlab_project_ids : "procject-${id}" => "attribute.project_id/${id}"
12+
} : {
13+
for id in var.gitlab_group_ids : "group-${id}" => "attribute.namespace_id/${id}"
14+
}
15+
principal_sets = {
16+
for key, subject in local.principal_subjects : key => "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.this.name}/${subject}"
17+
}
818

919
# Ensure the account_id is always 28 characters or less
1020
sa_name_prefix = "gwif-sa-"
@@ -44,12 +54,19 @@ locals {
4454

4555
gitlab_variables_description = replace(var.gitlab_variables_description, "{{MANAGER_NAME}}", var.gitlab_variables_description_manager_name)
4656
gitlab_variables_additional_final = {
47-
for key, value in var.gitlab_variables_additional :
48-
key => merge(
49-
value,
50-
{
51-
description = replace(value.description, "{{MANAGER_NAME}}", var.gitlab_variables_description_manager_name)
52-
}
53-
)
57+
for item in flatten([
58+
for gitlab_resource_id in local.is_gitlab_group_level ? var.gitlab_group_ids : var.gitlab_project_ids : [
59+
for key, value in var.gitlab_variables_additional : [
60+
merge(
61+
value,
62+
{
63+
gitlab_resource_id = gitlab_resource_id,
64+
key = key,
65+
description = replace(value.description, "{{MANAGER_NAME}}", var.gitlab_variables_description_manager_name)
66+
}
67+
)
68+
]
69+
]
70+
]) : "${item.key}--${item.gitlab_resource_id}" => item
5471
}
5572
}

main.tf

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,27 @@ resource "google_iam_workload_identity_pool" "this" {
1616
lifecycle {
1717
# Prevent creation of resources if the module is not configured correctly
1818
precondition {
19-
condition = var.gitlab_group_id > 0 || var.gitlab_project_id > 0
20-
error_message = "Either gitlab_group_id or gitlab_project_id must be provided."
19+
condition = length(var.gitlab_group_ids) > 0 || length(var.gitlab_project_ids) > 0
20+
error_message = "Either gitlab_group_ids or gitlab_project_ids must be provided."
2121
}
2222

2323
precondition {
24-
condition = (var.gitlab_group_id > 0) != (var.gitlab_project_id > 0)
25-
error_message = "Only one of gitlab_group_id or gitlab_project_id should be provided, not both."
24+
condition = (length(var.gitlab_group_ids) > 0) != (length(var.gitlab_project_ids) > 0)
25+
error_message = "Only one of gitlab_group_ids or gitlab_project_ids should be provided, not both."
2626
}
2727
}
2828
}
2929

3030
resource "google_iam_workload_identity_pool_provider" "this" {
31+
for_each = local.attribute_conditions
32+
3133
project = var.gcp_project_id
3234
workload_identity_pool_id = google_iam_workload_identity_pool.this.workload_identity_pool_id
3335
workload_identity_pool_provider_id = "provider-${substr(local.resource_name_suffix, 0, 32 - length("provider-"))}"
3436
display_name = local.provider_display_name
3537
description = "OIDC identity pool provider for ${var.name}"
3638
attribute_mapping = var.gcp_workload_identity_pool_provider_attribute_mapping
37-
attribute_condition = local.attribute_condition
39+
attribute_condition = each.value
3840

3941
oidc {
4042
issuer_uri = var.gitlab_instance_url
@@ -58,7 +60,9 @@ data "google_service_account" "this" {
5860
}
5961

6062
resource "google_service_account_iam_member" "this" {
63+
for_each = local.principal_sets
64+
6165
service_account_id = local.sa_name
6266
role = "roles/iam.workloadIdentityUser"
63-
member = local.principal_set
67+
member = each.value
6468
}

outputs.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ output "service_account_email" {
1414
}
1515

1616
output "principal_set" {
17-
description = "The principal set string used for IAM bindings."
18-
value = local.principal_set
17+
description = "The principal sets string used for IAM bindings."
18+
value = local.principal_sets
1919
}
2020

2121
# GitLab variables outputs

variables.tf

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,25 @@ variable "gcp_workload_identity_pool_provider_attribute_mapping" {
4242
}
4343

4444
# GitLab variables
45-
variable "gitlab_group_id" {
46-
description = "The GitLab group ID to allow access from. Use this for group-level access."
47-
type = number
48-
default = 0
45+
variable "gitlab_group_ids" {
46+
description = "The GitLab group IDs to allow access from. Use this for group-level access."
47+
type = list(number)
48+
default = []
4949

5050
validation {
51-
condition = var.gitlab_group_id >= 0
52-
error_message = "gitlab_group_id must be a valid GitLab group ID or 0 for non-set value (everything will be configured for project-level access)."
51+
condition = length(var.gitlab_group_ids) == 0 || alltrue([for id in var.gitlab_group_ids : id > 0])
52+
error_message = "gitlab_group_ids must be a valid list of GitLab group IDs or an empty list for non-set value (everything will be configured for project-level access)."
5353
}
5454
}
5555

56-
variable "gitlab_project_id" {
57-
description = "The GitLab project ID to allow access from. Use this for project-level access."
58-
type = number
59-
default = 0
56+
variable "gitlab_project_ids" {
57+
description = "The GitLab project IDs to allow access from. Use this for project-level access."
58+
type = list(number)
59+
default = []
6060

6161
validation {
62-
condition = var.gitlab_project_id >= 0
63-
error_message = "gitlab_project_id must be a valid GitLab project ID or 0 for non-set value (everything will be configured for group-level access)."
62+
condition = length(var.gitlab_project_ids) == 0 || alltrue([for id in var.gitlab_project_ids : id > 0])
63+
error_message = "gitlab_project_ids must be a valid list of GitLab project IDs or an empty list for non-set value (everything will be configured for group-level access)."
6464
}
6565
}
6666

0 commit comments

Comments
 (0)