diff --git a/blueprints/cloud-operations/README.md b/blueprints/cloud-operations/README.md index 36e4c41bca..88d55d4e82 100644 --- a/blueprints/cloud-operations/README.md +++ b/blueprints/cloud-operations/README.md @@ -62,3 +62,8 @@ This [blueprint](./onprem-sa-key-management) shows how to manage IAM Service Acc This [blueprint](./unmanaged-instances-healthcheck) shows how to leverage [Serverless VPC Access](https://cloud.google.com/vpc/docs/configure-serverless-vpc-access) and Cloud Functions to organize a highly performant TCP healtheck for unmanaged GCE instances.
+ +## Workload identity federation for Terraform Enterprise workflow + This [blueprint](./terraform-enterprise-wif) shows how to configure [Wokload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation) between [Terraform Cloud/Enterprise](https://developer.hashicorp.com/terraform/enterprise) instance and Google Cloud. + +
diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/README.md b/blueprints/cloud-operations/terraform-enterprise-wif/README.md new file mode 100644 index 0000000000..4bb282c560 --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/README.md @@ -0,0 +1,115 @@ +# Configuring workload identity federation for Terraform Cloud/Enterprise workflow + +The most common way to use Terraform Cloud for GCP deployments is to store a GCP Service Account Key as a part of TFE Workflow configuration, as we all know there are security risks due to the fact that keys are long term credentials that could be compromised. + +Workload identity federation enables applications running outside of Google Cloud to replace long-lived service account keys with short-lived access tokens. This is achieved by configuring Google Cloud to trust an external identity provider, so applications can use the credentials issued by the external identity provider to impersonate a service account. + +This blueprint shows how to set up [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation) between [Terraform Cloud/Enterprise](https://developer.hashicorp.com/terraform/enterprise) instance and Google Cloud. This will be possible by configuring workload identity federation to trust oidc tokens generated for a specific workflow in a Terraform Enterprise organization. + +The following diagram illustrates how the VM will get a short-lived access token and use it to access a resource: + + ![Sequence diagram](diagram.png) + +## Running the blueprint + +### Create Terraform Enterprise Workflow +If you don't have an existing Terraform Enterprise organization you can sign up for a [free trial](https://app.terraform.io/public/signup/account) account. + +Create a new Workspace for a `CLI-driven workflow` (Identity Federation will work for any workflow type, but for simplicity of the blueprint we use CLI driven workflow). + +Note workspace name and id (id starts with `ws-`), we will use them on a later stage. + +Go to the organization settings and note the org name and id (id starts with `org-`). + +### Deploy GCP Workload Identity Pool Provider for Terraform Enterprise + +> **_NOTE:_** This is a preparation part and should be executed on behalf of a user with enough permissions. + +Required permissions when new project is created: + - Project Creator on the parent folder/org. + + Required permissions when an existing project is used: + - Workload Identity Admin on the project level + - Project IAM Admin on the project level + +Fill out required variables, use TFE Org and Workspace IDs from the previous steps (IDs are not the names). +```bash +cd gcp-workload-identity-provider + +mv terraform.auto.tfvars.template terraform.auto.tfvars + +vi terraform.auto.tfvars +``` + +Authenticate using application default credentials, execute terraform code and deploy resources +``` +gcloud auth application-default login + +terraform init + +terraform apply +``` + +As a result a set of outputs will be provided (your values will be different), note the output since we will use it on the next steps. + +``` +impersonate_service_account_email = "sa-tfe@fe-test-oidc.iam.gserviceaccount.com" +project_id = "tfe-test-oidc" +workload_identity_audience = "//iam.googleapis.com/projects/476538149566/locations/global/workloadIdentityPools/tfe-pool/providers/tfe-provider" +workload_identity_pool_provider_id = "projects/476538149566/locations/global/workloadIdentityPools/tfe-pool/providers/tfe-provider" +``` + +### Configure OIDC provider for your TFE Workflow + +To enable OIDC for a TFE workflow it's enough to setup an environment variable `TFC_WORKLOAD_IDENTITY_AUDIENCE`. + +Go the the Workflow -> Variables and add a new variable `TFC_WORKLOAD_IDENTITY_AUDIENCE` equal to the value of `workload_identity_audience` output, in our example it's: + +``` +TFC_WORKLOAD_IDENTITY_AUDIENCE = "//iam.googleapis.com/projects/476538149566/locations/global/workloadIdentityPools/tfe-pool/providers/tfe-provider" +``` + +At that point we setup GCP Identity Federation to trust TFE generated OIDC tokens, so the TFE workflow can use the token to impersonate a GCP Service Account. + +## Testing the blueprint + +In order to test the setup we will deploy a GCS bucket from TFE Workflow using OIDC token for Service Account Impersonation. + +### Configure backend and variables + +First, we need to configure TFE Remote backend for our testing terraform code, use TFE Organization name and workspace name (names are not the same as ids) + +``` +cd ../tfc-workflow-using-wif + +mv backend.tf.template backend.tf + + +vi backend.tf + +``` + +Fill out variables based on the output from the preparation steps: + +``` +mv terraform.auto.tfvars.template terraform.auto.tfvars + +vi terraform.auto.tfvars + +``` + +### Authenticate terraform for triggering CLI-driven workflow + +Follow this [documentation](https://learn.hashicorp.com/tutorials/terraform/cloud-login) to login ti terraform cloud from the CLI. + +### Trigger the workflow + +``` +terraform init + +terraform apply +``` + +As a result we have a successfully deployed GCS bucket from Terraform Enterprise workflow using Workload Identity Federation. + +Once done testing, you can clean up resources by running `terraform destroy` first in the `tfc-workflow-using-wif` and then `gcp-workload-identity-provider` folders. diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/diagram.png b/blueprints/cloud-operations/terraform-enterprise-wif/diagram.png new file mode 100644 index 0000000000..d4e6f82e9d Binary files /dev/null and b/blueprints/cloud-operations/terraform-enterprise-wif/diagram.png differ diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/README.md b/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/README.md new file mode 100644 index 0000000000..40e00f8678 --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/README.md @@ -0,0 +1,33 @@ +# GCP Workload Identity Provider for Terraform Enterprise + +This terraform code is a part of [GCP Workload Identity Federation for Terraform Enterprise](../) blueprint. + +The codebase provisions the following list of resources: + +- GCS Bucket + + +## Variables + +| name | description | type | required | default | +|---|---|:---:|:---:|:---:| +| [billing_account](variables.tf#L16) | Billing account id used as default for new projects. | string | ✓ | | +| [project_id](variables.tf#L38) | Existing project id. | string | ✓ | | +| [tfe_organization_id](variables.tf#L43) | | | ✓ | | +| [tfe_workspace_id](variables.tf#L48) | | | ✓ | | +| [issuer_uri](variables.tf#L65) | Terraform Enterprise uri. Replace the uri if a self hosted instance is used. | string | | "https://app.terraform.io/" | +| [parent](variables.tf#L27) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | string | | null | +| [project_create](variables.tf#L21) | Create project instead of using an existing one. | bool | | true | +| [workload_identity_pool_id](variables.tf#L53) | Workload identity pool id. | string | | "tfe-pool" | +| [workload_identity_pool_provider_id](variables.tf#L59) | Workload identity pool provider id. | string | | "tfe-provider" | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| [impersonate_service_account_email](outputs.tf#L31) | | | +| [project_id](outputs.tf#L16) | | | +| [workload_identity_audience](outputs.tf#L26) | | | +| [workload_identity_pool_provider_id](outputs.tf#L21) | GCP workload identity pool provider ID. | | + + diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/main.tf b/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/main.tf new file mode 100644 index 0000000000..5ced2e3c57 --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/main.tf @@ -0,0 +1,91 @@ +# Copyright 2022 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 +# +# https://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. + + +############################################################################### +# GCP PROJECT # +############################################################################### + +module "project" { + source = "../../../../modules/project" + name = var.project_id + project_create = var.project_create + parent = var.parent + billing_account = var.billing_account + services = [ + "iam.googleapis.com", + "cloudresourcemanager.googleapis.com", + "iamcredentials.googleapis.com", + "sts.googleapis.com", + "storage.googleapis.com" + ] +} + +############################################################################### +# Workload Identity Pool and Provider # +############################################################################### + +resource "google_iam_workload_identity_pool" "tfe-pool" { + project = module.project.project_id + workload_identity_pool_id = var.workload_identity_pool_id + display_name = "TFE Pool" + description = "Identity pool for Terraform Enterprise OIDC integration" +} + +resource "google_iam_workload_identity_pool_provider" "tfe-pool-provider" { + project = module.project.project_id + workload_identity_pool_id = google_iam_workload_identity_pool.tfe-pool.workload_identity_pool_id + workload_identity_pool_provider_id = var.workload_identity_pool_provider_id + display_name = "TFE Pool Provider" + description = "OIDC identity pool provider for TFE Integration" + # Use condition to make sure only token generated for a specific TFE Org can be used across org workspaces + attribute_condition = "attribute.terraform_organization_id == \"${var.tfe_organization_id}\"" + attribute_mapping = { + "google.subject" = "assertion.sub" + "attribute.aud" = "assertion.aud" + "attribute.terraform_run_phase" = "assertion.terraform_run_phase" + "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" + } + oidc { + # Should be different if self hosted TFE instance is used + issuer_uri = var.issuer_uri + } +} + +############################################################################### +# Service Account and IAM bindings # +############################################################################### + +module "sa-tfe" { + source = "../../../../modules/iam-service-account" + project_id = module.project.project_id + name = "sa-tfe" + + iam = { + # We allow only tokens generated by a specific TFE workspace impersonation of the service account, + # that way one identity pool can be used for a TFE Organization, but every workspace will be able to impersonate only a specifc SA + "roles/iam.workloadIdentityUser" = ["principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.tfe-pool.name}/attribute.terraform_workspace_id/${var.tfe_workspace_id}"] + } + + iam_project_roles = { + "${module.project.project_id}" = [ + "roles/storage.admin" + ] + } +} diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/outputs.tf b/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/outputs.tf new file mode 100644 index 0000000000..79cea39a27 --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/outputs.tf @@ -0,0 +1,34 @@ +# Copyright 2022 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 +# +# https://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. + + +output "project_id" { + description = "GCP Project ID." + value = module.project.project_id +} + +output "workload_identity_pool_provider_id" { + description = "GCP workload identity pool provider ID." + value = google_iam_workload_identity_pool_provider.tfe-pool-provider.name +} + +output "workload_identity_audience" { + description = "TFC Workload Identity Audience." + value = "//iam.googleapis.com/${google_iam_workload_identity_pool_provider.tfe-pool-provider.name}" +} + +output "impersonate_service_account_email" { + description = "Service account to be impersonated by workload identity." + value = module.sa-tfe.email +} diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/terraform.auto.tfvars.template b/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/terraform.auto.tfvars.template new file mode 100644 index 0000000000..645eea0b9c --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/terraform.auto.tfvars.template @@ -0,0 +1,20 @@ +# Copyright 2022 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 +# +# https://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. + + +parent = "folders/437102807785" +project_id = "my-project-id" +tfe_organization_id = "org-W3bz9neazHrZz99U" +tfe_workspace_id = "ws-DFxEE3NmeMdaAvoK" +billing_account = "015617-1B8CBC-AF10D9" diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/variables.tf b/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/variables.tf new file mode 100644 index 0000000000..62163d1782 --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider/variables.tf @@ -0,0 +1,69 @@ +# Copyright 2022 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 +# +# https://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. + + +variable "billing_account" { + description = "Billing account id used as default for new projects." + type = string +} + +variable "project_create" { + description = "Create project instead of using an existing one." + type = bool + default = true +} + +variable "parent" { + description = "Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format." + type = string + default = null + validation { + condition = var.parent == null || can(regex("(organizations|folders)/[0-9]+", var.parent)) + error_message = "Parent must be of the form folders/folder_id or organizations/organization_id." + } +} + + +variable "project_id" { + description = "Existing project id." + type = string +} + +variable "tfe_organization_id" { + description = "TFE organization id." + type = string +} + +variable "tfe_workspace_id" { + description = "TFE workspace id." + type = string +} + +variable "workload_identity_pool_id" { + description = "Workload identity pool id." + type = string + default = "tfe-pool" +} + +variable "workload_identity_pool_provider_id" { + description = "Workload identity pool provider id." + type = string + default = "tfe-provider" +} + +variable "issuer_uri" { + description = "Terraform Enterprise uri. Replace the uri if a self hosted instance is used." + type = string + default = "https://app.terraform.io/" +} diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/README.md b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/README.md new file mode 100644 index 0000000000..5226dd64cc --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/README.md @@ -0,0 +1,19 @@ +# GCP Workload Identity Provider for Terraform Enterprise + +This terraform code is a part of [GCP Workload Identity Federation for Terraform Enterprise](../) blueprint. For instructions please refer to the blueprint [readme](../README.md). + +The codebase provisions the following list of resources: + +- GCS Bucket + + + +## Variables + +| name | description | type | required | default | +|---|---|:---:|:---:|:---:| +| [impersonate_service_account_email](variables.tf#L26) | | | ✓ | | +| [project_id](variables.tf#L16) | | | ✓ | | +| [workload_identity_pool_provider_id](variables.tf#L21) | GCP workload identity pool provider ID. | string | ✓ | | + + diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/backend.tf.template b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/backend.tf.template new file mode 100644 index 0000000000..87d4737dfb --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/backend.tf.template @@ -0,0 +1,29 @@ +# Copyright 2022 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 +# +# https://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. + + +# The block below configures Terraform to use the 'remote' backend with Terraform Cloud. +# For more information, see https://www.terraform.io/docs/backends/types/remote.html + +terraform { + backend "remote" { + organization = "" + + workspaces { + name = "" + } + } + + required_version = ">= 0.14.0" +} diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/main.tf b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/main.tf new file mode 100644 index 0000000000..5e03ada5fb --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/main.tf @@ -0,0 +1,25 @@ +# Copyright 2022 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 +# +# https://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. + + +############################################################################### +# TEST RESOURCE TO VALIDATE WIF # +############################################################################### + +resource "google_storage_bucket" "test-bucket" { + project = var.project_id + name = "${var.project_id}-tfe-oidc-test-bucket" + location = "US" + force_destroy = true +} diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/provider.tf b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/provider.tf new file mode 100644 index 0000000000..47f246200b --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/provider.tf @@ -0,0 +1,25 @@ +# Copyright 2022 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 +# +# https://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. + + +module "tfe_oidc" { + source = "./tfc-oidc" + + workload_identity_pool_provider_id = var.workload_identity_pool_provider_id + impersonate_service_account_email = var.impersonate_service_account_email +} + +provider "google" { + credentials = module.tfe_oidc.credentials +} diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/terraform.auto.tfvars.template b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/terraform.auto.tfvars.template new file mode 100644 index 0000000000..efea4cc996 --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/terraform.auto.tfvars.template @@ -0,0 +1,17 @@ +# Copyright 2022 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 +# +# https://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. + +project_id = "tfe-oidc-workflow" +workload_identity_pool_provider_id = "projects/683987109094/locations/global/workloadIdentityPools/tfe-pool/providers/tfe-provider" +impersonate_service_account_email = "sa-tfe@tfe-oidc-workflow2.iam.gserviceaccount.com" diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/README.md b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/README.md new file mode 100644 index 0000000000..bb8d79831f --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/README.md @@ -0,0 +1,40 @@ +# Terraform Enterprise OIDC Credential for GCP Workload Identity Federation + +This is a helper module to prepare GCP Credentials from Terraform Enterprise workload identity token. For more information see [Terraform Enterprise Workload Identity Federation](../) blueprint. + +## Example +```hcl +module "tfe_oidc" { + source = "./tfe_oidc" + + workload_identity_pool_provider_id = "projects/683987109094/locations/global/workloadIdentityPools/tfe-pool/providers/tfe-provider" + impersonate_service_account_email = "tfe-test@tfe-test-wif.iam.gserviceaccount.com" +} + +provider "google" { + credentials = module.tfe_oidc.credentials +} + +provider "google-beta" { + credentials = module.tfe_oidc.credentials +} + +# tftest skip +``` + + +## Variables + +| name | description | type | required | default | +|---|---|:---:|:---:|:---:| +| [impersonate_service_account_email](variables.tf#L22) | Service account to be impersonated by workload identity federation. | string | ✓ | | +| [workload_identity_pool_provider_id](variables.tf#L17) | GCP workload identity pool provider ID. | string | ✓ | | +| [tmp_oidc_token_path](variables.tf#L27) | Name of the temporary file where TFC OIDC token will be stored to authentificate terraform provider google. | string | | ".oidc_token" | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| [credentials](outputs.tf#L17) | | | + + diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/main.tf b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/main.tf new file mode 100644 index 0000000000..2c510a6a17 --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/main.tf @@ -0,0 +1,23 @@ +/** + * Copyright 2022 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 { + audience = "//iam.googleapis.com/${var.workload_identity_pool_provider_id}" +} + +data "external" "oidc_token_file" { + program = ["bash", "${path.module}/write_token.sh", "${var.tmp_oidc_token_path}"] +} diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/outputs.tf b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/outputs.tf new file mode 100644 index 0000000000..fbcea8c229 --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/outputs.tf @@ -0,0 +1,26 @@ +/** + * Copyright 2022 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. + */ + +output "credentials" { + value = jsonencode({ + "type" : "external_account", + "audience" : "${local.audience}", + "subject_token_type" : "urn:ietf:params:oauth:token-type:jwt", + "token_url" : "https://sts.googleapis.com/v1/token", + "credential_source" : data.external.oidc_token_file.result + "service_account_impersonation_url" : "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${var.impersonate_service_account_email}:generateAccessToken" + }) +} diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/variables.tf b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/variables.tf new file mode 100644 index 0000000000..06f310da98 --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/variables.tf @@ -0,0 +1,31 @@ +/** + * Copyright 2022 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. + */ + +variable "workload_identity_pool_provider_id" { + description = "GCP workload identity pool provider ID." + type = string +} + +variable "impersonate_service_account_email" { + description = "Service account to be impersonated by workload identity federation." + type = string +} + +variable "tmp_oidc_token_path" { + description = "Name of the temporary file where TFC OIDC token will be stored to authentificate terraform provider google." + type = string + default = ".oidc_token" +} diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/versions.tf b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/versions.tf new file mode 100644 index 0000000000..a079e99c4f --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/versions.tf @@ -0,0 +1,17 @@ +# Copyright 2022 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 +# +# https://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. + +terraform { + required_version = ">= 1.3.1" +} diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/write_token.sh b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/write_token.sh new file mode 100644 index 0000000000..2f7e30a2c0 --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/tfc-oidc/write_token.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Copyright 2022 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 +# +# https://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. + +# Exit if any of the intermediate steps fail +set -e + +FILENAME=$@ + +echo $TFC_WORKLOAD_IDENTITY_TOKEN > $FILENAME + +echo -n "{\"file\":\"${FILENAME}\"}" diff --git a/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/variables.tf b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/variables.tf new file mode 100644 index 0000000000..3f36c2ca65 --- /dev/null +++ b/blueprints/cloud-operations/terraform-enterprise-wif/tfc-workflow-using-wif/variables.tf @@ -0,0 +1,29 @@ +# Copyright 2022 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 +# +# https://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. + + +variable "project_id" { + description = "GCP project ID." + type = string +} + +variable "workload_identity_pool_provider_id" { + description = "GCP workload identity pool provider ID." + type = string +} + +variable "impersonate_service_account_email" { + description = "Service account to be impersonated by workload identity." + type = string +} diff --git a/tests/blueprints/cloud_operations/terraform-enterprise-wif/gcp-workload-identity-provider/__init__.py b/tests/blueprints/cloud_operations/terraform-enterprise-wif/gcp-workload-identity-provider/__init__.py new file mode 100644 index 0000000000..6d6d1266c3 --- /dev/null +++ b/tests/blueprints/cloud_operations/terraform-enterprise-wif/gcp-workload-identity-provider/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2022 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. diff --git a/tests/blueprints/cloud_operations/terraform-enterprise-wif/gcp-workload-identity-provider/fixture/main.tf b/tests/blueprints/cloud_operations/terraform-enterprise-wif/gcp-workload-identity-provider/fixture/main.tf new file mode 100644 index 0000000000..3552740c2a --- /dev/null +++ b/tests/blueprints/cloud_operations/terraform-enterprise-wif/gcp-workload-identity-provider/fixture/main.tf @@ -0,0 +1,28 @@ +/** + * Copyright 2022 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. + */ + +module "test" { + source = "../../../../../../blueprints/cloud-operations/terraform-enterprise-wif/gcp-workload-identity-provider" + billing_account = var.billing_account + project_create = var.project_create + project_id = var.project_id + parent = var.parent + tfe_organization_id = var.tfe_organization_id + tfe_workspace_id = var.tfe_workspace_id + workload_identity_pool_id = var.workload_identity_pool_id + workload_identity_pool_provider_id = var.workload_identity_pool_provider_id + issuer_uri = var.issuer_uri +} diff --git a/tests/blueprints/cloud_operations/terraform-enterprise-wif/gcp-workload-identity-provider/fixture/variables.tf b/tests/blueprints/cloud_operations/terraform-enterprise-wif/gcp-workload-identity-provider/fixture/variables.tf new file mode 100644 index 0000000000..d99981c0cf --- /dev/null +++ b/tests/blueprints/cloud_operations/terraform-enterprise-wif/gcp-workload-identity-provider/fixture/variables.tf @@ -0,0 +1,68 @@ +# Copyright 2022 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 +# +# https://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. + +variable "billing_account" { + type = string + default = "1234-ABCD-1234" +} + +variable "project_create" { + type = bool + default = true +} + +variable "project_id" { + type = string + default = "project-1" +} + +variable "parent" { + description = "Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format." + type = string + default = null + validation { + condition = var.parent == null || can(regex("(organizations|folders)/[0-9]+", var.parent)) + error_message = "Parent must be of the form folders/folder_id or organizations/organization_id." + } +} + +variable "tfe_organization_id" { + description = "TFE organization id." + type = string + default = "org-123" +} + +variable "tfe_workspace_id" { + description = "TFE workspace id." + type = string + default = "ws-123" +} + +variable "workload_identity_pool_id" { + description = "Workload identity pool id." + type = string + default = "tfe-pool" +} + +variable "workload_identity_pool_provider_id" { + description = "Workload identity pool provider id." + type = string + default = "tfe-provider" +} + +variable "issuer_uri" { + description = "Terraform Enterprise uri. Replace the uri if a self hosted instance is used." + type = string + default = "https://app.terraform.io/" +} diff --git a/tests/blueprints/cloud_operations/terraform-enterprise-wif/gcp-workload-identity-provider/test_plan.py b/tests/blueprints/cloud_operations/terraform-enterprise-wif/gcp-workload-identity-provider/test_plan.py new file mode 100644 index 0000000000..228e51dfde --- /dev/null +++ b/tests/blueprints/cloud_operations/terraform-enterprise-wif/gcp-workload-identity-provider/test_plan.py @@ -0,0 +1,19 @@ +# Copyright 2022 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. + +def test_resources(e2e_plan_runner): + "Test that plan works and the numbers of resources is as expected." + modules, resources = e2e_plan_runner() + assert len(modules) == 2 + assert len(resources) == 10