{"id":24233825,"url":"https://github.com/memes/f5-bootstrap-gcp-project","last_synced_at":"2025-06-28T13:40:38.751Z","repository":{"id":45127594,"uuid":"261254649","full_name":"memes/f5-bootstrap-gcp-project","owner":"memes","description":"Terraform to setup F5's sales projects on GCP for automation","archived":false,"fork":false,"pushed_at":"2024-02-15T21:55:40.000Z","size":87,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-01-14T16:16:19.352Z","etag":null,"topics":["google","terraform"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/memes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2020-05-04T17:43:06.000Z","updated_at":"2022-01-06T19:26:40.000Z","dependencies_parsed_at":"2023-12-12T01:42:43.057Z","dependency_job_id":null,"html_url":"https://github.com/memes/f5-bootstrap-gcp-project","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memes%2Ff5-bootstrap-gcp-project","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memes%2Ff5-bootstrap-gcp-project/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memes%2Ff5-bootstrap-gcp-project/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/memes%2Ff5-bootstrap-gcp-project/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/memes","download_url":"https://codeload.github.com/memes/f5-bootstrap-gcp-project/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241853996,"owners_count":20031339,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["google","terraform"],"created_at":"2025-01-14T16:01:54.736Z","updated_at":"2025-03-04T13:25:39.358Z","avatar_url":"https://github.com/memes.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# F5 bootstrap project\n\n**OBSOLETE: This repo creates resources that follow best practices but are against\nF5 CISO rulesets.**\n\n\u003e NOTE: this repo is a poor substitute for a true GCP Project Factory and\n\u003e Organization policy. I recommend Google's published\n\u003e [Terraform modules](https://registry.terraform.io/modules/terraform-google-modules)\n\u003e to implement a fully defined approach to project creation and birthright\n\u003e accounts.\n\nUse these files to prepare existing F5 GCP projects for Terraform and Ansible\nautomation. During execution, Terraform will bootstrap the project to create\nthese resources:\n\n1. Terraform GCS bucket for remote state\n1. Enables Compute Engine and IAP APIs by default\n1. Enables OS Login for GCE instances at the project level\n1. A service account to use for Terraform automation\n   - with storage admin rights on Terraform state bucket\n   - with an extendible set of roles at project level\n   - with optional impersonation enabled for AD group(s)\n1. A service account to use for Ansible automation\n   - with an extendible set of roles at project level\n   - with optional impersonation enabled for AD group(s)\n\n## Usage\n\nThis repo uses file based environment configurations in preference to Terraform\nworkspaces. Per-environment configurations are stored in\n`env/ENV/main.tf`, where ENV and name represents the GCP project\nenvironment to manage.\n\n### To make a change to an **existing** project\n\nTo make changes to an existing project to add additional impersonation groups,\nor to enable other GCP APIs\n\n1. Fork the repo\n1. Edit the relevant environment `main.tf` file\n1. Execute standard Terraform process\n\n   ```shell\n   terraform init\n   terraform plan\n   terraform apply\n   ```\n\n1. Push the changes to GitHub and open a PR to merge to `main`\n\n### To bootstrap a **new** project\n\nIf you need to bootstrap a new GCP project to support Terraform automation, you\nmust apply the Terraform twice.\n\n#### A. Bootstrap project\n\n1. Fork the repo\n1. Create a new `env` folder for the project, using the contents of [env/new-template](env/new-template/)\n   as a starting point.\n1. Edit `main.tf` so that:\n   - GCS backend is disabled (lines 18-21); this will be reverted after the state\n     bucket is bootstrapped.\n   - Set `project_id` variable to match the target GCP project id\n1. Add other overrides as needed by setting the corresponding module variable\n   - Add AD groups that will be granted the ability to impersonate Terraform\n     service account\n   - *Optional:* Add any Google Cloud APIs that need to be enabled\n   - *Optional:* Add any additional roles that should be granted to the\n     Terraform and/or Ansible service accounts\n1. Execute Terraform to create the new resources\n\n   ```shell\n   terraform init\n   terraform apply\n   ```\n\n   ```shell\n   ...\n   tf_sa = terraform@PROJECT_ID.iam.gserviceccount.com\n   ...\n   tf_state_bucket = TF_BUCKET_NAME\n   ```\n\nAt this point a the service accounts are created and a new GCS bucket is ready to manage Terraform state.\n\n#### B. Transfer state to new GCS bucket\n\n1. Uncomment lines 18-21 of [main.tf](env/new-template/main.tf#L18) to (re-)enable GCS backend\n1. Set the `bucket` parameter to match the Terraform state bucket that was an\n   output from step A.4\n1. Add a unique prefix for the bootstrap state.\n\n   E.g.\n\n   ```hcl\n   ...\n     backend \"gcs\" {\n       bucket = \"TF_BUCKET_NAME\"\n       prefix = \"foundations/terraform-bootstrap\"\n     }\n   }\n   ```\n\n1. Reinitialise Terraform to migrate the state to GCS bucket\n\n   ```shell\n   terraform init -migrate-state\n   ```\n\n   ```shell\n   ...\n   Initializing the backend...\n   Do you want to copy existing state to the new backend?\n      Pre-existing state was found while migrating the previous \"local\" backend to the newly configured \"gcs\" backend. No existing state was found in the newly configured \"gcs\" backend. Do you want to copy this state to the new \"gcs\" backend? Enter \"yes\" to copy and \"no\" to start with an empty state.\n\n      Enter a value: yes\n\n   Successfully configured the backend \"gcs\"! Terraform will automatically use this backend unless the backend configuration changes.\n   ...\n   ```\n\n   The Terraform state is now stored in GCS bucket and can be shared by others that are managing the project.\n\n1. Commit and push the changes to GitHub, and open a PR to merge to `main`\n\n## Optional next-steps (not automated)\n\nIn my article I talked about the recommendations usually provided by a true\nProject Factory module, but I decided not to include all of those in this script\nbecause it may break existing deployments or interfere with another SEs\nresources. If you are certain that it is safe to do so, use these commands to\ndisable the Default Compute service account, and remove the `default` network.\n\n### Disable Default Compute service account\n\n1. Get the target project number from UI, or command line\n\n   ```shell\n   gcloud projects describe PROJECT_ID --format 'value(projectNumber)'\n   ```\n\n   ```shell\n   nnnnnnnnnnnn\n   ```\n\n1. Disable the Default Compute service account\n\n   ```shell\n   gcloud iam service-accounts disable nnnnnnnnnnnn-compute@developer.gserviceaccount.com --project PROJECT_ID\n   ```\n\n   ```shell\n   Disabled service account [nnnnnnnnnnnn-compute@developer.gserviceaccount.com].\n   ```\n\n\u003c!-- markdownlint-disable no-inline-html --\u003e\n\u003c!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK --\u003e\n## Requirements\n\n| Name | Version |\n|------|---------|\n| \u003ca name=\"requirement_terraform\"\u003e\u003c/a\u003e [terraform](#requirement\\_terraform) | \u003e= 1.3 |\n| \u003ca name=\"requirement_google\"\u003e\u003c/a\u003e [google](#requirement\\_google) | \u003e= 4.56 |\n\n## Modules\n\nNo modules.\n\n## Resources\n\n| Name | Type |\n|------|------|\n| [google_dns_managed_zone.zone](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/dns_managed_zone) | resource |\n| [google_iam_workload_identity_pool.automation](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool) | resource |\n| [google_iam_workload_identity_pool_provider.github_oidc](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider) | resource |\n| [google_iam_workload_identity_pool_provider.terraform_oidc](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider) | resource |\n| [google_project_iam_member.ansible_sa_roles](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_iam_member) | resource |\n| [google_project_iam_member.oslogin](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_iam_member) | resource |\n| [google_project_iam_member.tf_sa_roles](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_iam_member) | resource |\n| [google_project_service.apis](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_service) | resource |\n| [google_service_account.ansible](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account) | resource |\n| [google_service_account.tf](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account) | resource |\n| [google_service_account_iam_member.bind_ansible_workload_identity](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account_iam_member) | resource |\n| [google_service_account_iam_member.bind_tf_workload_identity](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account_iam_member) | resource |\n| [google_service_account_iam_member.tf_impersonate_token](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account_iam_member) | resource |\n| [google_service_account_iam_member.tf_impersonate_user](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account_iam_member) | resource |\n| [google_storage_bucket.tf_bucket](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket) | resource |\n| [google_storage_bucket_iam_member.tf_bucket_admin](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket_iam_member) | resource |\n\n## Inputs\n\n| Name | Description | Type | Default | Required |\n|------|-------------|------|---------|:--------:|\n| \u003ca name=\"input_project_id\"\u003e\u003c/a\u003e [project\\_id](#input\\_project\\_id) | The existing project id that will have a Terraform service account added. | `string` | n/a | yes |\n| \u003ca name=\"input_ansible_sa_impersonate_groups\"\u003e\u003c/a\u003e [ansible\\_sa\\_impersonate\\_groups](#input\\_ansible\\_sa\\_impersonate\\_groups) | A list of groups that will be allowed to impersonate the Ansible service account.\u003cbr\u003eIf no groups are supplied, impersonation will not be setup by the script.\u003cbr\u003eE.g.\u003cbr\u003eansible\\_sa\\_impersonate\\_groups = [\u003cbr\u003e  \"devsecops@example.com\",\u003cbr\u003e  \"admins@example.com\",\u003cbr\u003e] | `list(string)` | `[]` | no |\n| \u003ca name=\"input_ansible_sa_name\"\u003e\u003c/a\u003e [ansible\\_sa\\_name](#input\\_ansible\\_sa\\_name) | The name of the Ansible service account to add to the project. Default is\u003cbr\u003e'ansible'. | `string` | `\"ansible\"` | no |\n| \u003ca name=\"input_ansible_sa_roles\"\u003e\u003c/a\u003e [ansible\\_sa\\_roles](#input\\_ansible\\_sa\\_roles) | A list of IAM roles to assign to the Terraform service account. Defaults to a set\u003cbr\u003eneeded to manage Compute resources, GCS buckets, and IAM assignments. | `list(string)` | \u003cpre\u003e[\u003cbr\u003e  \"roles/compute.viewer\",\u003cbr\u003e  \"roles/compute.osLogin\"\u003cbr\u003e]\u003c/pre\u003e | no |\n| \u003ca name=\"input_apis\"\u003e\u003c/a\u003e [apis](#input\\_apis) | An optional list of GCP APIs to enable in the project. | `list(string)` | \u003cpre\u003e[\u003cbr\u003e  \"storage-api.googleapis.com\",\u003cbr\u003e  \"storage-component.googleapis.com\",\u003cbr\u003e  \"compute.googleapis.com\",\u003cbr\u003e  \"iap.googleapis.com\",\u003cbr\u003e  \"oslogin.googleapis.com\",\u003cbr\u003e  \"iam.googleapis.com\",\u003cbr\u003e  \"iamcredentials.googleapis.com\",\u003cbr\u003e  \"cloudresourcemanager.googleapis.com\",\u003cbr\u003e  \"secretmanager.googleapis.com\"\u003cbr\u003e]\u003c/pre\u003e | no |\n| \u003ca name=\"input_domains\"\u003e\u003c/a\u003e [domains](#input\\_domains) | An optional set of DNS domains to create in the project. Default is empty list. | `list(string)` | `[]` | no |\n| \u003ca name=\"input_labels\"\u003e\u003c/a\u003e [labels](#input\\_labels) | An optional set of key:value string pairs that will be added to resources. | `map(string)` | `{}` | no |\n| \u003ca name=\"input_oslogin_accounts\"\u003e\u003c/a\u003e [oslogin\\_accounts](#input\\_oslogin\\_accounts) | A list of fully-qualified IAM accounts that will be allowed to use OS Login to\u003cbr\u003eVMs.\u003cbr\u003eE.g.\u003cbr\u003eoslogin\\_accounts = [\u003cbr\u003e  \"group:devsecops@example.com\",\u003cbr\u003e  \"group:admins@example.com\",\u003cbr\u003e  \"user:jane@example.com\",\u003cbr\u003e] | `list(string)` | `[]` | no |\n| \u003ca name=\"input_tf_bucket_location\"\u003e\u003c/a\u003e [tf\\_bucket\\_location](#input\\_tf\\_bucket\\_location) | The location where the bucket will be created; this could be a GCE region, or a\u003cbr\u003edual-region or multi-region specifier. Default is to create a multi-region bucket\u003cbr\u003ein 'US'. | `string` | `\"US\"` | no |\n| \u003ca name=\"input_tf_bucket_name\"\u003e\u003c/a\u003e [tf\\_bucket\\_name](#input\\_tf\\_bucket\\_name) | The name of a GCS bucket to create for Terraform state storage. This name must be\u003cbr\u003eunique in GCP. If blank, (the default), the name will be 'tf-PROJECT\\_ID', where\u003cbr\u003ePROJECT\\_ID is the unique project identifier. | `string` | `\"\"` | no |\n| \u003ca name=\"input_tf_sa_impersonators\"\u003e\u003c/a\u003e [tf\\_sa\\_impersonators](#input\\_tf\\_sa\\_impersonators) | A list of fully-qualified IAM accounts that will be allowed to impersonate the\u003cbr\u003eTerraform service account. If no accounts are supplied, impersonation will not\u003cbr\u003ebe setup by the script.\u003cbr\u003eE.g.\u003cbr\u003etf\\_sa\\_impersonators = [\u003cbr\u003e  \"group:devsecops@example.com\",\u003cbr\u003e  \"group:admins@example.com\",\u003cbr\u003e  \"user:jane@example.com\",\u003cbr\u003e  \"serviceAccount:ci-cd@project.iam.gserviceaccount.com\",\u003cbr\u003e] | `list(string)` | `[]` | no |\n| \u003ca name=\"input_tf_sa_name\"\u003e\u003c/a\u003e [tf\\_sa\\_name](#input\\_tf\\_sa\\_name) | The name of the Terraform service account to add to the project. Default is\u003cbr\u003e'terraform'. | `string` | `\"terraform\"` | no |\n| \u003ca name=\"input_tf_sa_roles\"\u003e\u003c/a\u003e [tf\\_sa\\_roles](#input\\_tf\\_sa\\_roles) | A list of IAM roles to assign to the Terraform service account. Defaults to a set\u003cbr\u003eneeded to manage Compute resources, GCS buckets, IAM, and Secret Manager assignments. | `list(string)` | \u003cpre\u003e[\u003cbr\u003e  \"roles/compute.admin\",\u003cbr\u003e  \"roles/iam.serviceAccountAdmin\",\u003cbr\u003e  \"roles/iam.serviceAccountKeyAdmin\",\u003cbr\u003e  \"roles/storage.admin\",\u003cbr\u003e  \"roles/resourcemanager.projectIamAdmin\",\u003cbr\u003e  \"roles/secretmanager.admin\",\u003cbr\u003e  \"roles/iam.roleAdmin\"\u003cbr\u003e]\u003c/pre\u003e | no |\n| \u003ca name=\"input_workload_identity\"\u003e\u003c/a\u003e [workload\\_identity](#input\\_workload\\_identity) | If any field is true, enable a workload identity pool and establish an OIDC\u003cbr\u003eprovider for each enabled provider. Default value does not enable workload identity. | \u003cpre\u003eobject({\u003cbr\u003e    github    = bool\u003cbr\u003e    terraform = bool\u003cbr\u003e  })\u003c/pre\u003e | `null` | no |\n\n## Outputs\n\n| Name | Description |\n|------|-------------|\n| \u003ca name=\"output_ansible_sa\"\u003e\u003c/a\u003e [ansible\\_sa](#output\\_ansible\\_sa) | The fully-qualified Ansible service account identifier. |\n| \u003ca name=\"output_tf_sa\"\u003e\u003c/a\u003e [tf\\_sa](#output\\_tf\\_sa) | The fully-qualified Terraform service account identifier. |\n| \u003ca name=\"output_tf_state_bucket\"\u003e\u003c/a\u003e [tf\\_state\\_bucket](#output\\_tf\\_state\\_bucket) | The GCS bucket that will hold Terraform state. |\n| \u003ca name=\"output_workload_identity_pool\"\u003e\u003c/a\u003e [workload\\_identity\\_pool](#output\\_workload\\_identity\\_pool) | The full-qualified workload identity pool name, if created. |\n\u003c!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK --\u003e\n\u003c!-- markdownlint-enable no-inline-html --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmemes%2Ff5-bootstrap-gcp-project","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmemes%2Ff5-bootstrap-gcp-project","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmemes%2Ff5-bootstrap-gcp-project/lists"}