Leverage project-level workload identity in FAST CI/CD (#3535)
* Leverage project-level WIF in FAST CI/CD * add new context namespace, improve outputs, fix tests and inventories * make YAML linter happy * README
This commit is contained in:
committed by
GitHub
parent
0ff2e8c56b
commit
8c29512890
@@ -28,6 +28,8 @@
|
||||
- [Context-based replacement in the folders factory](#context-based-replacement-in-the-folders-factory)
|
||||
- [Project factory](#project-factory)
|
||||
- [CI/CD configuration](#cicd-configuration)
|
||||
- [Read-write and read-only impersonation](#read-write-and-read-only-impersonation)
|
||||
- [Customized IAM principal sets](#customized-iam-principal-sets)
|
||||
- [Okta](#okta)
|
||||
- [Leveraging classic FAST Stages](#leveraging-classic-fast-stages)
|
||||
- [VPC Service Controls](#vpc-service-controls)
|
||||
@@ -296,6 +298,7 @@ This is a simple reference table of available interpolation namespaces, refer to
|
||||
- `$tag_values:my_value`
|
||||
- `$vpc_host_projects:my_project`
|
||||
- `$vpc_sc_perimeters:my_perimeter`
|
||||
- `$workload_identity_providers:my_project/my_pool/my_provider`
|
||||
|
||||
### Factory data
|
||||
|
||||
@@ -319,7 +322,7 @@ The default paths point to the dataset in the `data` folder which deploys a FAST
|
||||
folder-level factory to define the resource management hierarchy and individual folder attributes (IAM, org policies, tag bindings, etc.); also supports defining folder-level IaC resources
|
||||
- **projects** (`datasets/classic/projects`) \
|
||||
folder-level factory to define projects and their attributes (projejct factory)
|
||||
- **cicd** (`datasets/classic/cicd.yaml`) \
|
||||
- **cicd** (`datasets/classic/cicd-workflows.yaml`) \
|
||||
file-level factory to define CI/CD configurations for this and subsequent stages
|
||||
|
||||
### Defaults configuration
|
||||
@@ -502,7 +505,7 @@ values:
|
||||
# [...]
|
||||
```
|
||||
|
||||
An exception to the namespaced-based context replacements is in IAM conditions, where Terraform limitations force use of native string templating, as in the example below.
|
||||
An exception to the namespaced-based context replacements is in IAM conditions and organization policies, where Terraform limitations force use of native string templating, as in the example below.
|
||||
|
||||
```yaml
|
||||
iam_bindings:
|
||||
@@ -575,44 +578,80 @@ The provided project configurations also create several key resources for the st
|
||||
|
||||
### CI/CD configuration
|
||||
|
||||
CI/CD support is implemented in a similar way to classic/legacy FAST, except for being driven by a factory that points to a single file.
|
||||
CI/CD support is implemented via two different sets of connfigurations:
|
||||
|
||||
This allows defining a single Workload Identity provider that will be used to exchange external tokens for the pipelines, and one or more workflows that can interpolate internal (from the project factory) or external (user defined) attributes.
|
||||
- [Workload Identity](https://docs.cloud.google.com/iam/docs/workload-identity-federation) providers are defined in project configurations
|
||||
- CI/CD service accounts and templated workflow generation are defined in a dedicated configuration (`var.factories_config.cicd_workflows`).
|
||||
|
||||
This is the default file which implements a workflow for this stage. To enable it, pass the file path to the `factories_config.cicd` variable.
|
||||
The default approach is to define a Workload Identity provider in the `iac-0` project, or in an additional project dedicated to this task. This is achieved by adding a `workload_identity_pools` block to the project configuration, like in the following example.
|
||||
|
||||
```yaml
|
||||
workload_identity_federation:
|
||||
pool_name: iac-0
|
||||
project: $project_ids:iac-0
|
||||
providers:
|
||||
github:
|
||||
# the condition is optional but recommended, use your GitHub org name
|
||||
attribute_condition: attribute.repository_owner=="my_org"
|
||||
issuer: github
|
||||
# custom_settings:
|
||||
# issuer_uri:
|
||||
# audiences: []
|
||||
# jwks_json_path:
|
||||
workflows:
|
||||
org_setup:
|
||||
template: github
|
||||
workload_identity_provider:
|
||||
id: $wif_providers:github
|
||||
audiences: []
|
||||
repository:
|
||||
name: org-setup
|
||||
branch: main
|
||||
output_files:
|
||||
storage_bucket: $storage_buckets:iac-0/iac-outputs
|
||||
providers:
|
||||
apply: $output_files:providers/0-org-setup
|
||||
plan: $output_files:providers/0-org-setup-ro
|
||||
files:
|
||||
- tfvars/0-boostrap.auto.tfvars.json
|
||||
service_accounts:
|
||||
apply: $iam_principals:service_accounts/iac-0/iac-org-cicd-rw
|
||||
plan: $iam_principals:service_accounts/iac-0/iac-org-cicd-ro
|
||||
# projects/iac-0.yaml
|
||||
|
||||
workload_identity_pools:
|
||||
default:
|
||||
display_name: Default pool for CI/CD.
|
||||
providers:
|
||||
github-default:
|
||||
display_name: GitHub (example org).
|
||||
attribute_condition: attribute.repository_owner=="example"
|
||||
identity_provider:
|
||||
oidc:
|
||||
template: github
|
||||
gitlab-default:
|
||||
display_name: Gitlab (example org).
|
||||
attribute_condition: attribute.namespace_path=="example"
|
||||
identity_provider:
|
||||
oidc:
|
||||
template: gitlab
|
||||
```
|
||||
|
||||
The above configuration can be easily extended to support multiple pools and providers, and is not limited to OpenId Connect but can also leverage other provider types. Check the project module or project schema for the full interface.
|
||||
|
||||
Once one or more providers have been defined they can be referenced in the CI/CD cofniguration file. The following example defines a workflow configuration for this stage.
|
||||
|
||||
```yaml
|
||||
# cicd-workflows.yaml
|
||||
|
||||
org-setup:
|
||||
provider_files:
|
||||
apply: 0-org-setup-providers.tf
|
||||
plan: 0-org-setup-providers-ro.tf
|
||||
repository:
|
||||
name: example/0-org-setup
|
||||
type: github
|
||||
apply_branches:
|
||||
- master
|
||||
- fast-dev
|
||||
service_accounts:
|
||||
apply: $iam_principals:service_accounts/iac-0/iac-org-cicd-rw
|
||||
plan: $iam_principals:service_accounts/iac-0/iac-org-cicd-ro
|
||||
tfvars_files:
|
||||
- 0-org-setup.auto.tfvars
|
||||
workload_identity:
|
||||
provider: $workload_identity_providers:iac-0/default/github-default
|
||||
iam_principalsets:
|
||||
template: github
|
||||
```
|
||||
|
||||
The configuration prepares a sample workflow file for the target repository, and configures IAM on the service accounts referenced in the configuration, so that repository tokens can impersonate them via the Workload Identity provider.
|
||||
|
||||
#### Read-write and read-only impersonation
|
||||
|
||||
The access pattern implemented above allows impersonation from any branch to the read-only (`-ro`) service account, and impersonation from explicitly mentioned branches to the read-write (`rw`) service account. This ensures that PR-related actions run with limited privileges, and higher level privileges are only used for merges after PR checks and approvals. If a more relaxed approach where any branch can access the read-write service account, simply omit the `repository.apply_branches` block.
|
||||
|
||||
#### Customized IAM principal sets
|
||||
|
||||
The format of the IAM principalsets used to grant impersonation permissions to the exchanged token can either leverage internally defined templates via the `workload_identity.iam_principalsets.template` attribute, or be explicitly defined so that fine-tuning is possible, or different sets of principals are allowed. The following example is the explicit format equivalent to the template used above.
|
||||
|
||||
```yaml
|
||||
org-setup:
|
||||
# identical lines omitted
|
||||
workload_identity:
|
||||
provider: $workload_identity_providers:iac-0/default/github-default
|
||||
iam_principalsets:
|
||||
apply: principalSet://iam.googleapis.com/%s/attribute.fast_sub/repo:%s:ref:refs/heads/%s
|
||||
plan: principalSet://iam.googleapis.com/%s/attribute.repository/%s
|
||||
```
|
||||
|
||||
#### Okta
|
||||
@@ -654,7 +693,7 @@ workflows:
|
||||
plan: $iam_principals:service_accounts/iac-0/iac-org-cicd-ro
|
||||
```
|
||||
|
||||
Finally you will need to modify the following org policies and IAM permissions in `datasets/classic/organization/org-policies/iam.yaml` file:
|
||||
Finally you will need to modify the following org policies and IAM permissions in `datasets/classic/organization/org-policies/iam.yaml` file:
|
||||
|
||||
- Under `org_polices` add your Okta provider URL :
|
||||
|
||||
@@ -669,11 +708,11 @@ org_policies:
|
||||
- https://app.terraform.io
|
||||
- https://<REPLACE_WITH_ORG_NAME>.okta.com/oauth2/default // Modify this
|
||||
```
|
||||
|
||||
This configuration adds Okta to the list of allowed Workload Identity providers in your GCP organization.
|
||||
|
||||
- Under `iac-org-cicd-ro` and `iac-org-cicd-rw` service accounts add `roles/iam.workloadIdentityUser` to each of them:
|
||||
|
||||
|
||||
```yaml
|
||||
iac-org-cicd-ro:
|
||||
display_name: IaC service account for org setup CI/CD (read-only).
|
||||
@@ -695,6 +734,7 @@ This configuration adds Okta to the list of allowed Workload Identity providers
|
||||
roles/iam.workloadIdentityUser:
|
||||
- principalSet://iam.googleapis.com/projects/<REPLACE_WITH_IAC_PROJECT_NUMBER>/locations/global/workloadIdentityPools/iac-0/* // Modify this
|
||||
```
|
||||
|
||||
This allows identities from the Workload Identity Pool to impersonate both IaC service accounts.
|
||||
</details>
|
||||
|
||||
@@ -732,24 +772,24 @@ Define values for the `var.environments` variable in a tfvars file.
|
||||
| name | description | modules | resources |
|
||||
|---|---|---|---|
|
||||
| [billing.tf](./billing.tf) | None | <code>billing-account</code> | |
|
||||
| [cicd.tf](./cicd.tf) | None | <code>iam-service-account</code> | <code>google_storage_bucket_object</code> · <code>local_file</code> |
|
||||
| [cicd-workflows-preconditions.tf](./cicd-workflows-preconditions.tf) | None | | <code>terraform_data</code> |
|
||||
| [cicd-workflows.tf](./cicd-workflows.tf) | None | <code>iam-service-account</code> | <code>google_storage_bucket_object</code> · <code>local_file</code> |
|
||||
| [factory.tf](./factory.tf) | None | <code>project-factory</code> | |
|
||||
| [identity-providers-defs.tf](./identity-providers-defs.tf) | None | | |
|
||||
| [imports.tf](./imports.tf) | None | | |
|
||||
| [main.tf](./main.tf) | Module-level locals and resources. | | <code>terraform_data</code> |
|
||||
| [organization.tf](./organization.tf) | None | <code>organization</code> | |
|
||||
| [output-files.tf](./output-files.tf) | None | | <code>google_storage_bucket_object</code> · <code>local_file</code> |
|
||||
| [outputs.tf](./outputs.tf) | Module outputs. | | |
|
||||
| [variables.tf](./variables.tf) | Module variables. | | |
|
||||
| [wif-definitions.tf](./wif-definitions.tf) | Workload Identity provider definitions. | | |
|
||||
| [wif-providers.tf](./wif-providers.tf) | None | | <code>google_iam_workload_identity_pool</code> · <code>google_iam_workload_identity_pool_provider</code> |
|
||||
|
||||
## Variables
|
||||
|
||||
| name | description | type | required | default |
|
||||
|---|---|:---:|:---:|:---:|
|
||||
| [context](variables.tf#L17) | Context-specific interpolations. | <code title="object({ custom_roles = optional(map(string), {}) email_addresses = optional(map(string), {}) folder_ids = optional(map(string), {}) iam_principals = optional(map(string), {}) locations = optional(map(string), {}) kms_keys = optional(map(string), {}) notification_channels = optional(map(string), {}) project_ids = optional(map(string), {}) service_account_ids = optional(map(string), {}) tag_keys = optional(map(string), {}) tag_values = optional(map(string), {}) vpc_host_projects = optional(map(string), {}) vpc_sc_perimeters = optional(map(string), {}) })">object({…})</code> | | <code>{}</code> |
|
||||
| [factories_config](variables.tf#L38) | Configuration for the resource factories or external data. | <code title="object({ billing_accounts = optional(string, "datasets/classic/billing-accounts") cicd = optional(string) defaults = optional(string, "datasets/classic/defaults.yaml") folders = optional(string, "datasets/classic/folders") organization = optional(string, "datasets/classic/organization") project_templates = optional(string, "datasets/classic/templates") projects = optional(string, "datasets/classic/projects") })">object({…})</code> | | <code>{}</code> |
|
||||
| [org_policies_imports](variables.tf#L53) | List of org policies to import. These need to also be defined in data files. | <code>list(string)</code> | | <code>[]</code> |
|
||||
| [context](variables.tf#L17) | Context-specific interpolations. | <code title="object({ custom_roles = optional(map(string), {}) email_addresses = optional(map(string), {}) folder_ids = optional(map(string), {}) iam_principals = optional(map(string), {}) locations = optional(map(string), {}) kms_keys = optional(map(string), {}) notification_channels = optional(map(string), {}) project_ids = optional(map(string), {}) service_account_ids = optional(map(string), {}) tag_keys = optional(map(string), {}) tag_values = optional(map(string), {}) vpc_host_projects = optional(map(string), {}) vpc_sc_perimeters = optional(map(string), {}) workload_identity_providers = optional(map(string), {}) })">object({…})</code> | | <code>{}</code> |
|
||||
| [factories_config](variables.tf#L39) | Configuration for the resource factories or external data. | <code title="object({ billing_accounts = optional(string, "datasets/classic/billing-accounts") cicd_workflows = optional(string) defaults = optional(string, "datasets/classic/defaults.yaml") folders = optional(string, "datasets/classic/folders") organization = optional(string, "datasets/classic/organization") project_templates = optional(string, "datasets/classic/templates") projects = optional(string, "datasets/classic/projects") })">object({…})</code> | | <code>{}</code> |
|
||||
| [org_policies_imports](variables.tf#L54) | List of org policies to import. These need to also be defined in data files. | <code>list(string)</code> | | <code>[]</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ on:
|
||||
env:
|
||||
FAST_SERVICE_ACCOUNT: ${service_accounts.apply}
|
||||
FAST_SERVICE_ACCOUNT_PLAN: ${service_accounts.plan}
|
||||
FAST_WIF_PROVIDER: ${workload_identity.pool_id}
|
||||
FAST_WIF_PROVIDER: ${workload_identity_provider}
|
||||
SSH_AUTH_SOCK: /tmp/ssh_agent.sock
|
||||
TF_PROVIDERS_FILE: ${provider_files.apply}
|
||||
TF_PROVIDERS_FILE_PLAN: ${provider_files.plan}
|
||||
|
||||
59
fast/stages/0-org-setup/cicd-workflows-preconditions.tf
Normal file
59
fast/stages/0-org-setup/cicd-workflows-preconditions.tf
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright 2025 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.
|
||||
*/
|
||||
|
||||
resource "terraform_data" "precondition-cicd" {
|
||||
lifecycle {
|
||||
precondition {
|
||||
condition = alltrue([
|
||||
for k, v in local.cicd_workflows :
|
||||
v.repository.name != null && v.repository.type != null
|
||||
])
|
||||
error_message = "Incomplete repository configuration in CI/CD workflows."
|
||||
}
|
||||
precondition {
|
||||
condition = alltrue([
|
||||
for k, v in local.cicd_workflows :
|
||||
v.provider_files.apply != null && v.provider_files.plan != null
|
||||
])
|
||||
error_message = "Incomplete provider files configuration in CI/CD workflows."
|
||||
}
|
||||
precondition {
|
||||
condition = alltrue([
|
||||
for k, v in local.cicd_workflows :
|
||||
v.service_accounts.apply != null && v.service_accounts.plan != null
|
||||
])
|
||||
error_message = "Incomplete service account configuration in CI/CD workflows."
|
||||
}
|
||||
precondition {
|
||||
condition = alltrue([
|
||||
for k, v in local.cicd_workflows : (
|
||||
v.workload_identity.provider != null &&
|
||||
v.workload_identity.iam_principalsets.plan != null
|
||||
)
|
||||
])
|
||||
error_message = "Incomplete workload identity configuration in CI/CD workflows."
|
||||
}
|
||||
precondition {
|
||||
condition = alltrue([
|
||||
for k, v in local.cicd_workflows : (
|
||||
length(v.repository.apply_branches) == 0 ||
|
||||
v.workload_identity.iam_principalsets.apply != null
|
||||
)
|
||||
])
|
||||
error_message = "Missing apply principalset in CI/CD workflows."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,57 +16,69 @@
|
||||
|
||||
locals {
|
||||
# raw configuration (the wif files are also users of this local)
|
||||
cicd = try(yamldecode(file(local.paths.cicd)), {})
|
||||
_cicd_workflows = try(yamldecode(file(local.paths.cicd_workflows)), {})
|
||||
# dereferencing maps
|
||||
cicd_ctx_sa = {
|
||||
for k, v in merge(local.ctx.iam_principals, module.factory.iam_principals) :
|
||||
"$iam_principals:${k}" => v
|
||||
}
|
||||
cicd_ctx_wif = try({
|
||||
"$wif_pools:${local.wif_pool_name}" = google_iam_workload_identity_pool.default[0].name
|
||||
}, {})
|
||||
# normalize workflow configurations
|
||||
cicd_ctx_wif = {
|
||||
for k, v in merge(
|
||||
local.ctx.workload_identity_providers, local.workload_identity_providers
|
||||
) : "$workload_identity_providers:${k}" => v
|
||||
}
|
||||
# normalize workflow configurations, correctness is checked via preconditions
|
||||
cicd_workflows = {
|
||||
for k, v in lookup(local.cicd, "workflows", {}) : k => merge(v, {
|
||||
iam_principal_templates = {
|
||||
branch = local.wif_defs[v.repository.type].principal_branch
|
||||
repo = local.wif_defs[v.repository.type].principal_repo
|
||||
for k, v in local._cicd_workflows : k => {
|
||||
provider_files = {
|
||||
apply = try(v.provider_files.apply, null)
|
||||
plan = try(v.provider_files.plan, null)
|
||||
}
|
||||
repository = merge(v.repository, {
|
||||
repository = {
|
||||
apply_branches = try(v.repository.apply_branches, [])
|
||||
})
|
||||
service_accounts = {
|
||||
apply = trimprefix(try(
|
||||
local.cicd_ctx_sa[v.service_accounts.apply], v.service_accounts.apply
|
||||
), "serviceAccount:")
|
||||
plan = trimprefix(try(
|
||||
local.cicd_ctx_sa[v.service_accounts.plan], v.service_accounts.plan
|
||||
), "serviceAccount:")
|
||||
name = try(v.repository.name, null)
|
||||
type = try(v.repository.type, null)
|
||||
}
|
||||
workload_identity = {
|
||||
audiences = try(v.workload_identity.audiences, [])
|
||||
pool_id = try(
|
||||
local.cicd_ctx_wif[v.workload_identity.pool_id],
|
||||
v.workload_identity.pool_id
|
||||
service_accounts = {
|
||||
apply = try(
|
||||
trimprefix(
|
||||
local.cicd_ctx_sa[v.service_accounts.apply], "serviceAccount:"
|
||||
),
|
||||
v.service_accounts.apply,
|
||||
null
|
||||
)
|
||||
plan = try(
|
||||
trimprefix(
|
||||
local.cicd_ctx_sa[v.service_accounts.plan], "serviceAccount:"
|
||||
),
|
||||
v.service_accounts.plan,
|
||||
null
|
||||
)
|
||||
}
|
||||
})
|
||||
if(
|
||||
try(local.wif_defs[v.repository.type], null) != null &&
|
||||
try(v.provider_files.apply, null) != null &&
|
||||
try(v.provider_files.plan, null) != null &&
|
||||
try(v.repository.name, null) != null &&
|
||||
try(v.service_accounts.apply, null) != null &&
|
||||
try(v.service_accounts.plan, null) != null &&
|
||||
try(v.workload_identity.pool_id, null) != null
|
||||
)
|
||||
tfvars_files = try(v.tfvars_files, [])
|
||||
workload_identity = {
|
||||
provider = try(
|
||||
local.cicd_ctx_wif[v.workload_identity.provider],
|
||||
v.workload_identity.provider,
|
||||
null
|
||||
)
|
||||
iam_principalsets = try(
|
||||
local.wif_iam_templates[v.workload_identity.iam_principalsets.template],
|
||||
{
|
||||
apply = try(v.workload_identity.iam_principalsets.apply)
|
||||
plan = try(v.workload_identity.iam_principalsets.plan)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
# generate workflow files contents
|
||||
cicd_workflows_contents = {
|
||||
for k, v in local.cicd_workflows : k => templatefile(
|
||||
"assets/workflow-${v.repository.type}.yaml", merge(v, {
|
||||
outputs_bucket = local.of_outputs_bucket
|
||||
stage_name = k
|
||||
outputs_bucket = local.of_outputs_bucket
|
||||
stage_name = k
|
||||
workload_identity_provider = v.workload_identity.provider
|
||||
})
|
||||
)
|
||||
}
|
||||
@@ -84,15 +96,15 @@ module "cicd-sa-apply" {
|
||||
length(each.value.repository.apply_branches) == 0
|
||||
? [
|
||||
format(
|
||||
each.value.iam_principal_templates.repo,
|
||||
each.value.workload_identity.pool_id,
|
||||
each.value.workload_identity.iam_principalsets.plan,
|
||||
each.value.workload_identity.provider,
|
||||
each.value.repository.name
|
||||
)
|
||||
]
|
||||
: [
|
||||
for v in each.value.repository.apply_branches : format(
|
||||
each.value.iam_principal_templates.branch,
|
||||
each.value.workload_identity.pool_id,
|
||||
each.value.workload_identity.iam_principalsets.apply,
|
||||
each.value.workload_identity.provider,
|
||||
each.value.repository.name,
|
||||
v
|
||||
)
|
||||
@@ -111,8 +123,8 @@ module "cicd-sa-plan" {
|
||||
iam = {
|
||||
"roles/iam.workloadIdentityUser" = [
|
||||
format(
|
||||
each.value.iam_principal_templates.repo,
|
||||
each.value.workload_identity.pool_id,
|
||||
each.value.workload_identity.iam_principalsets.plan,
|
||||
each.value.workload_identity.provider,
|
||||
each.value.repository.name
|
||||
)
|
||||
]
|
||||
41
fast/stages/0-org-setup/identity-providers-defs.tf
Normal file
41
fast/stages/0-org-setup/identity-providers-defs.tf
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright 2025 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.
|
||||
*/
|
||||
|
||||
locals {
|
||||
wif_iam_templates = {
|
||||
# https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect
|
||||
github = {
|
||||
apply = "principalSet://iam.googleapis.com/%s/attribute.fast_sub/repo:%s:ref:refs/heads/%s"
|
||||
plan = "principalSet://iam.googleapis.com/%s/attribute.repository/%s"
|
||||
}
|
||||
# https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html#token-payload
|
||||
gitlab = {
|
||||
apply = "principalSet://iam.googleapis.com/%s/attribute.sub/project_path:%s:ref_type:branch:ref:%s"
|
||||
plan = "principalSet://iam.googleapis.com/%s/attribute.repository/%s"
|
||||
}
|
||||
# https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/workload-identity-tokens#token-structure
|
||||
terraform = {
|
||||
apply = "principalSet://iam.googleapis.com/%s/attribute.terraform_workspace_id/%s"
|
||||
plan = "principalSet://iam.googleapis.com/%s/attribute.terraform_project_id/%s"
|
||||
}
|
||||
# https://developer.okta.com/docs/api/openapi/okta-oauth/guides/overview/
|
||||
okta = {
|
||||
apply = "principalSet://iam.googleapis.com/%s/attribute.sub/project_path:%s:ref_type:branch:ref:%s"
|
||||
plan = "principalSet://iam.googleapis.com/%s/attribute.repository/%s"
|
||||
member = "principalSet://iam.googleapis.com/%s/*"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,12 @@ locals {
|
||||
defaults = try(local._defaults.projects.defaults, {})
|
||||
overrides = try(local._defaults.projects.overrides, {})
|
||||
}
|
||||
workload_identity_providers = merge([
|
||||
for k, v in module.factory.projects : {
|
||||
for wk, wv in v.workload_identity_providers :
|
||||
"${k}/${wk}" => wv.pool
|
||||
}
|
||||
]...)
|
||||
}
|
||||
|
||||
# TODO: streamine location replacements
|
||||
|
||||
@@ -90,12 +90,11 @@ locals {
|
||||
project_ids = local.of_ctx.project_ids,
|
||||
project_numbers = module.factory.project_numbers
|
||||
# project_numbers = module.factory.project_numbers
|
||||
service_accounts = module.factory.service_account_emails
|
||||
storage_buckets = module.factory.storage_buckets
|
||||
tag_values = local.of_ctx.tag_values
|
||||
workforce_identity_providers = try(
|
||||
module.organization[0].workforce_identity_provider_names, {}
|
||||
)
|
||||
service_accounts = module.factory.service_account_emails
|
||||
storage_buckets = module.factory.storage_buckets
|
||||
tag_values = local.of_ctx.tag_values
|
||||
workload_identity_providers = local.workload_identity_providers
|
||||
workforce_identity_providers = module.organization[0].workforce_identity_providers
|
||||
}
|
||||
}
|
||||
of_universe_domain = try(
|
||||
|
||||
134
fast/stages/0-org-setup/schemas/cicd-workflows.schema.json
Normal file
134
fast/stages/0-org-setup/schemas/cicd-workflows.schema.json
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "CI/CD Configuration",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^[a-z-][a-z0-9-]+$": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"provider_files",
|
||||
"repository",
|
||||
"service_accounts",
|
||||
"workload_identity"
|
||||
],
|
||||
"properties": {
|
||||
"provider_files": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"apply",
|
||||
"plan"
|
||||
],
|
||||
"properties": {
|
||||
"apply": {
|
||||
"type": "string"
|
||||
},
|
||||
"plan": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"github",
|
||||
"gitlab"
|
||||
]
|
||||
},
|
||||
"apply_branches": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_accounts": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"apply",
|
||||
"plan"
|
||||
],
|
||||
"properties": {
|
||||
"apply": {
|
||||
"type": "string"
|
||||
},
|
||||
"plan": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tfvars_files": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"workload_identity": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"provider",
|
||||
"iam_principalsets"
|
||||
],
|
||||
"properties": {
|
||||
"provider": {
|
||||
"type": "string"
|
||||
},
|
||||
"iam_principalsets": {
|
||||
"type": "object",
|
||||
"oneOf": [
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"template"
|
||||
],
|
||||
"properties": {
|
||||
"template": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"github",
|
||||
"gitlab",
|
||||
"okta",
|
||||
"terraform"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"apply",
|
||||
"plan"
|
||||
],
|
||||
"properties": {
|
||||
"apply": {
|
||||
"type": "string"
|
||||
},
|
||||
"plan": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
fast/stages/0-org-setup/schemas/cicd-workflows.schema.md
Normal file
35
fast/stages/0-org-setup/schemas/cicd-workflows.schema.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# CI/CD Configuration
|
||||
|
||||
<!-- markdownlint-disable MD036 -->
|
||||
|
||||
## Properties
|
||||
|
||||
*additional properties: false*
|
||||
|
||||
- **`^[a-z-][a-z0-9-]+$`**: *object*
|
||||
<br>*additional properties: false*
|
||||
- ⁺**provider_files**: *object*
|
||||
<br>*additional properties: false*
|
||||
- ⁺**apply**: *string*
|
||||
- ⁺**plan**: *string*
|
||||
- ⁺**repository**: *object*
|
||||
<br>*additional properties: false*
|
||||
- ⁺**name**: *string*
|
||||
- ⁺**type**: *string*
|
||||
<br>*enum: ['github', 'gitlab']*
|
||||
- **apply_branches**: *array*
|
||||
- items: *string*
|
||||
- ⁺**service_accounts**: *object*
|
||||
<br>*additional properties: false*
|
||||
- ⁺**apply**: *string*
|
||||
- ⁺**plan**: *string*
|
||||
- **tfvars_files**: *array*
|
||||
- items: *string*
|
||||
- ⁺**workload_identity**: *object*
|
||||
<br>*additional properties: false*
|
||||
- ⁺**provider**: *string*
|
||||
- ⁺**iam_principalsets**: *object*
|
||||
|
||||
## Definitions
|
||||
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "CI/CD Configuration",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"workflows": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^[a-z-][a-z0-9-]+$": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"provider_files",
|
||||
"repository",
|
||||
"service_accounts",
|
||||
"workload_identity"
|
||||
],
|
||||
"properties": {
|
||||
"provider_files": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"apply",
|
||||
"plan"
|
||||
],
|
||||
"properties": {
|
||||
"apply": {
|
||||
"type": "string"
|
||||
},
|
||||
"plan": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"github",
|
||||
"gitlab"
|
||||
]
|
||||
},
|
||||
"apply_branches": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"service_accounts": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"apply",
|
||||
"plan"
|
||||
],
|
||||
"properties": {
|
||||
"apply": {
|
||||
"type": "string"
|
||||
},
|
||||
"plan": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tfvars_files": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"workload_identity": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"pool_id"
|
||||
],
|
||||
"properties": {
|
||||
"pool_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"audiences": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"workload_identity_federation": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"pool_name",
|
||||
"project"
|
||||
],
|
||||
"properties": {
|
||||
"pool_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"project": {
|
||||
"type": "string"
|
||||
},
|
||||
"providers": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^[a-z-][a-z0-9-]+$": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"issuer"
|
||||
],
|
||||
"properties": {
|
||||
"attribute_condition": {
|
||||
"type": "string"
|
||||
},
|
||||
"custom_settings": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"issuer_uri": {
|
||||
"type": "string"
|
||||
},
|
||||
"audiences": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"jwks_json_path": {
|
||||
"type": "string"
|
||||
},
|
||||
"okta": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"organization_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"auth_server_name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"issuer": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"github",
|
||||
"gitlab",
|
||||
"terraform",
|
||||
"okta"
|
||||
]
|
||||
},
|
||||
"provider_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
# CI/CD Configuration
|
||||
|
||||
<!-- markdownlint-disable MD036 -->
|
||||
|
||||
## Properties
|
||||
|
||||
*additional properties: false*
|
||||
|
||||
- **workflows**: *object*
|
||||
<br>*additional properties: false*
|
||||
- **`^[a-z-][a-z0-9-]+$`**: *object*
|
||||
<br>*additional properties: false*
|
||||
- ⁺**provider_files**: *object*
|
||||
<br>*additional properties: false*
|
||||
- ⁺**apply**: *string*
|
||||
- ⁺**plan**: *string*
|
||||
- ⁺**repository**: *object*
|
||||
<br>*additional properties: false*
|
||||
- ⁺**name**: *string*
|
||||
- ⁺**type**: *string*
|
||||
<br>*enum: ['github', 'gitlab']*
|
||||
- **apply_branches**: *array*
|
||||
- items: *string*
|
||||
- ⁺**service_accounts**: *object*
|
||||
<br>*additional properties: false*
|
||||
- ⁺**apply**: *string*
|
||||
- ⁺**plan**: *string*
|
||||
- **tfvars_files**: *array*
|
||||
- items: *string*
|
||||
- ⁺**workload_identity**: *object*
|
||||
<br>*additional properties: false*
|
||||
- ⁺**pool_id**: *string*
|
||||
- **audiences**: *array*
|
||||
- items: *string*
|
||||
- **workload_identity_federation**: *object*
|
||||
<br>*additional properties: false*
|
||||
- ⁺**pool_name**: *string*
|
||||
- ⁺**project**: *string*
|
||||
- **providers**: *object*
|
||||
<br>*additional properties: false*
|
||||
- **`^[a-z-][a-z0-9-]+$`**: *object*
|
||||
<br>*additional properties: false*
|
||||
- **attribute_condition**: *string*
|
||||
- **custom_settings**: *object*
|
||||
<br>*additional properties: false*
|
||||
- **issuer_uri**: *string*
|
||||
- **audiences**: *array*
|
||||
- items: *string*
|
||||
- **jwks_json_path**: *string*
|
||||
- **okta**: *object*
|
||||
<br>*additional properties: false*
|
||||
- **organization_name**: *string*
|
||||
- **auth_server_name**: *string*
|
||||
|
||||
## Definitions
|
||||
|
||||
|
||||
@@ -525,6 +525,12 @@
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"workload_identity_providers": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -17,19 +17,20 @@
|
||||
variable "context" {
|
||||
description = "Context-specific interpolations."
|
||||
type = object({
|
||||
custom_roles = optional(map(string), {})
|
||||
email_addresses = optional(map(string), {})
|
||||
folder_ids = optional(map(string), {})
|
||||
iam_principals = optional(map(string), {})
|
||||
locations = optional(map(string), {})
|
||||
kms_keys = optional(map(string), {})
|
||||
notification_channels = optional(map(string), {})
|
||||
project_ids = optional(map(string), {})
|
||||
service_account_ids = optional(map(string), {})
|
||||
tag_keys = optional(map(string), {})
|
||||
tag_values = optional(map(string), {})
|
||||
vpc_host_projects = optional(map(string), {})
|
||||
vpc_sc_perimeters = optional(map(string), {})
|
||||
custom_roles = optional(map(string), {})
|
||||
email_addresses = optional(map(string), {})
|
||||
folder_ids = optional(map(string), {})
|
||||
iam_principals = optional(map(string), {})
|
||||
locations = optional(map(string), {})
|
||||
kms_keys = optional(map(string), {})
|
||||
notification_channels = optional(map(string), {})
|
||||
project_ids = optional(map(string), {})
|
||||
service_account_ids = optional(map(string), {})
|
||||
tag_keys = optional(map(string), {})
|
||||
tag_values = optional(map(string), {})
|
||||
vpc_host_projects = optional(map(string), {})
|
||||
vpc_sc_perimeters = optional(map(string), {})
|
||||
workload_identity_providers = optional(map(string), {})
|
||||
})
|
||||
default = {}
|
||||
nullable = false
|
||||
@@ -39,7 +40,7 @@ variable "factories_config" {
|
||||
description = "Configuration for the resource factories or external data."
|
||||
type = object({
|
||||
billing_accounts = optional(string, "datasets/classic/billing-accounts")
|
||||
cicd = optional(string)
|
||||
cicd_workflows = optional(string)
|
||||
defaults = optional(string, "datasets/classic/defaults.yaml")
|
||||
folders = optional(string, "datasets/classic/folders")
|
||||
organization = optional(string, "datasets/classic/organization")
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
/**
|
||||
* Copyright 2025 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 Workload Identity provider definitions.
|
||||
|
||||
locals {
|
||||
wif_defs = {
|
||||
# https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect
|
||||
github = {
|
||||
attribute_mapping = {
|
||||
"google.subject" = "assertion.sub"
|
||||
"attribute.sub" = "assertion.sub"
|
||||
"attribute.actor" = "assertion.actor"
|
||||
"attribute.repository" = "assertion.repository"
|
||||
"attribute.repository_owner" = "assertion.repository_owner"
|
||||
"attribute.ref" = "assertion.ref"
|
||||
"attribute.fast_sub" = "\"repo:\" + assertion.repository + \":ref:\" + assertion.ref"
|
||||
}
|
||||
issuer_uri = "https://token.actions.githubusercontent.com"
|
||||
principal_branch = "principalSet://iam.googleapis.com/%s/attribute.fast_sub/repo:%s:ref:refs/heads/%s"
|
||||
principal_repo = "principalSet://iam.googleapis.com/%s/attribute.repository/%s"
|
||||
}
|
||||
# https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html#token-payload
|
||||
gitlab = {
|
||||
attribute_mapping = {
|
||||
"google.subject" = "assertion.sub"
|
||||
"attribute.sub" = "assertion.sub"
|
||||
"attribute.environment" = "assertion.environment"
|
||||
"attribute.environment_protected" = "assertion.environment_protected"
|
||||
"attribute.namespace_id" = "assertion.namespace_id"
|
||||
"attribute.namespace_path" = "assertion.namespace_path"
|
||||
"attribute.pipeline_id" = "assertion.pipeline_id"
|
||||
"attribute.pipeline_source" = "assertion.pipeline_source"
|
||||
"attribute.project_id" = "assertion.project_id"
|
||||
"attribute.project_path" = "assertion.project_path"
|
||||
"attribute.repository" = "assertion.project_path"
|
||||
"attribute.ref" = "assertion.ref"
|
||||
"attribute.ref_protected" = "assertion.ref_protected"
|
||||
"attribute.ref_type" = "assertion.ref_type"
|
||||
}
|
||||
issuer_uri = "https://gitlab.com"
|
||||
principal_branch = "principalSet://iam.googleapis.com/%s/attribute.sub/project_path:%s:ref_type:branch:ref:%s"
|
||||
principal_repo = "principalSet://iam.googleapis.com/%s/attribute.repository/%s"
|
||||
}
|
||||
# https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/workload-identity-tokens#token-structure
|
||||
terraform = {
|
||||
attribute_mapping = {
|
||||
"google.subject" = "assertion.terraform_workspace_id"
|
||||
"attribute.aud" = "assertion.aud"
|
||||
"attribute.terraform_run_phase" = "assertion.terraform_run_phase"
|
||||
"attribute.terraform_project_id" = "assertion.terraform_project_id"
|
||||
"attribute.terraform_project_name" = "assertion.terraform_project_name"
|
||||
"attribute.terraform_workspace_id" = "assertion.terraform_workspace_id"
|
||||
"attribute.terraform_workspace_name" = "assertion.terraform_workspace_name"
|
||||
"attribute.terraform_organization_id" = "assertion.terraform_organization_id"
|
||||
"attribute.terraform_organization_name" = "assertion.terraform_organization_name"
|
||||
"attribute.terraform_run_id" = "assertion.terraform_run_id"
|
||||
"attribute.terraform_full_workspace" = "assertion.terraform_full_workspace"
|
||||
}
|
||||
issuer_uri = "https://app.terraform.io"
|
||||
principal_branch = "principalSet://iam.googleapis.com/%s/attribute.terraform_workspace_id/%s"
|
||||
principal_repo = "principalSet://iam.googleapis.com/%s/attribute.terraform_project_id/%s"
|
||||
}
|
||||
# https://developer.okta.com/docs/api/openapi/okta-oauth/guides/overview/
|
||||
okta = {
|
||||
attribute_mapping = {
|
||||
"google.subject" = "assertion.sub"
|
||||
"attribute.sub" = "assertion.sub"
|
||||
}
|
||||
principal_branch = "principalSet://iam.googleapis.com/%s/attribute.sub/project_path:%s:ref_type:branch:ref:%s"
|
||||
principal_repo = "principalSet://iam.googleapis.com/%s/attribute.repository/%s"
|
||||
principal_member = "principalSet://iam.googleapis.com/%s/*"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/**
|
||||
* Copyright 2025 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.
|
||||
*/
|
||||
|
||||
locals {
|
||||
wif_ctx_project_ids = {
|
||||
for k, v in merge(var.context.project_ids, module.factory.project_ids) :
|
||||
"$project_ids:${k}" => v
|
||||
}
|
||||
wif_pool_name = try(
|
||||
local.cicd.workload_identity_federation.pool_name, "iac-0"
|
||||
)
|
||||
wif_project = try(local.cicd.workload_identity_federation.project, null)
|
||||
wif_providers = local.wif_project == null ? {} : {
|
||||
for k, v in try(local.cicd.workload_identity_federation.providers, {}) :
|
||||
k => merge(v, lookup(local.wif_defs, v.issuer, {}))
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_iam_workload_identity_pool" "default" {
|
||||
count = local.wif_project == null ? 0 : 1
|
||||
project = lookup(
|
||||
local.wif_ctx_project_ids, local.wif_project, local.wif_project
|
||||
)
|
||||
workload_identity_pool_id = local.wif_pool_name
|
||||
}
|
||||
|
||||
resource "google_iam_workload_identity_pool_provider" "default" {
|
||||
for_each = local.wif_providers
|
||||
project = google_iam_workload_identity_pool.default[0].project
|
||||
workload_identity_pool_id = (
|
||||
google_iam_workload_identity_pool.default[0].workload_identity_pool_id
|
||||
)
|
||||
workload_identity_pool_provider_id = lookup(each.value, "provider_id", each.key)
|
||||
attribute_condition = lookup(each.value, "attribute_condition", null)
|
||||
attribute_mapping = lookup(each.value, "attribute_mapping", {})
|
||||
oidc {
|
||||
# Setting an empty list configures allowed_audiences to the url of the provider
|
||||
allowed_audiences = try(each.value.custom_settings.audiences, [])
|
||||
# If users don't provide an issuer_uri, we set the public one for the platform chosen.
|
||||
issuer_uri = coalesce(
|
||||
try(each.value.custom_settings.issuer_uri, null),
|
||||
try("https://${each.value.custom_settings.okta.organization_name}/oauth2/${each.value.custom_settings.okta.auth_server_name}", null),
|
||||
try(each.value.issuer_uri, null),
|
||||
)
|
||||
# OIDC JWKs in JSON String format. If no value is provided, they key is
|
||||
# fetched from the `.well-known` path for the issuer_uri
|
||||
jwks_json = try(each.value.custom_settings.jwks_json, null)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user