/terraform-gcp-bootstrapper

automates almost all the boring setup bits for Github + GCP Cloud Build + Terraform, so you can get to work on your actual idea faster

Primary LanguageShellMIT LicenseMIT

terraform-gcp-bootstrapper

what is this?

This shell script automates many boring setup bits for Github, GCP Cloud Build and Terraform, so you can get to work on your actual idea much faster.

You supply:

  • a Github repository
  • a Github personal access token (details and opinions below)
  • the application ID for Google Cloud Build once you've set it up in your Github account

It will setup in GCP:

  • a new project to contain your experiment, associated with your billing account
  • a Terraform state bucket
  • a Secret in Secret Manager for your Github personal access token
  • a Github platform connection in Cloud Build
  • a Github repository connection in Cloud Build
  • three Cloud Build triggers:
    • on branch push, run a Terraform plan+apply
    • on manual trigger, run a Terraform plan+apply
    • on manual trigger, run a Terraform destroy
  • various IAM bits to make it all work

Some files will be added to the repository:

  • a Terraform backend definition, because you need one and why type it every time?
  • scripts to invoke the manual deploy & destroy triggers
  • a "Hello, world" Terraform output definition to give it something to chew on

Some files will be copied from wherever terraform-gcp-bootstrapper.sh is, if they exist there, otherwise you'll need to copy them yourself:

  • Cloud Build deploy pipeline YAML that runs Terraform and stores state in the state bucket
  • Cloud Build destroy pipeline YAML that runs Terraform and stores state in the state bucket

Perfect for quick experiments and prototypes.

YOU are responsible for your GCP cost, data and uptime!

Ugly disclaimers time.

I am not responsible for your Google Cloud Platform bill. YOU need to understand the cost impact of all resources and other billable usage in your account, and control it accordingly.

I am also not responsible for your Google Cloud Platform data. This implementation is designed to fail fast if anything doesn't look right, and all resources are created in a new project (and it attempts to avoid accidentally creating them in another project, such as if you happened to run...

gcloud config set project SOMEOTHERPROJECT

... while it is still creating resources in your new project. So it should be pretty safe, but ... ultimately the responsibility rests with you.

YOU are responsible for your Github account and access token security!

Audit your tokens regularly and consider how and where they are used. Consider creating them with expiry dates, knowing of course that if you do your pipeline will eventually stop working.

Install dependencies

Some preparation required. You only need to do these once.

Google Cloud CLI initial setup

Skip this if you can already gcloud projects create.

Otherwise, go here: https://cloud.google.com/sdk/docs/install

Google Cloud CLI alpha components

Once you have gcloud working with your Google Cloud account, you'll also need to install the optional alpha components, as some of the Cloud Build features, and also the ability to link a project to a billing account, are not yet in the general release version of gcloud.

gcloud components install alpha

Note that these are alpha components and should be treated as such.

Google Cloud Build application in Github Marketplace

Add the Cloud Build application to your Github account.

Once added, go to your application settings page and copy the Configure button's link for the Google Cloud Build application. It should look like this

https://github.com/settings/installations/38510777

You only just the number at the end. It will be a different number to the above example.

Put it (use your number, not mine!) in a file $HOME/shell-secrets/tokens/github/cloudbuild_install_id, and protect the directory from snooping other users, if any:

mkdir -p "$HOME/shell-secrets/tokens/github/"
chmod 700 "$HOME/shell-secrets/tokens/github/"
echo 38510777 > "$HOME/shell-secrets/tokens/github/cloudbuild_install_id"

That's it!

Setup an experiment!

Per-project Github setup:

  1. create a Github repository for your experiment

  2. go back to the application settings page and hit the Configure button for the Google Cloud Build application. Ensure it is allowed access to the repository you just created. If you allowed it access to all of your repositories, you won't need to do this, but I assume you didn't :-)

  3. create a Github personal access token with repo and user:read privileges. Use the repository name for the token comment so you can identify its purpose later. Put the token in $HOME/shell-secrets/tokens/github/NAME_OF_REPOSITORY_HERE, eg. if your repository is https://github.com/example/tf-gcp-rpg, your filename would be $HOME/shell-secrets/tokens/github/tf-gcp-rpg. I hope this makes sense.

Actually do things

  1. clone this repository somewhere
cd "$HOME/repo"
git clone git@github.com:jsleeio/terraform-gcp-bootstrapper.git
  1. clone your new experiment's repository (adjust names accordingly)
cd "$HOME/repo"
git clone git@github.com:example/tf-gcp-experiment
cd tf-gcp-experiment
  1. run it from within your new repo somewhere, and give it a name to use for the new GCP project it will create for your experiment. My preference is to use the same name for repository and project.
$HOME/repo/terraform-gcp-bootstrapper/terraform-gcp-bootstrapper.sh -p YOURPROJECT
  1. if all went well, some files should have been created in your repository. If the Cloud Build YAML files aren't there, you'll need to copy them from this repository, removing -sample from their names.
git add .
git commit -m 'initial setup'
git push
  1. go into the Cloud Build console in your new project. Was a build triggered? Did it work? Did you get a greeting in the log?

regarding Github personal access tokens

The instructions here suggest a token per experiment. This is annoying, to be sure, but it suits the context (experiments you create and destroy as required) quite well:

  • you'll always know what each token is for

  • each token is only stored within Secret Manager within project in which it is used; there are no annoying cross-project relationships to audit/setup

  • destroying one experiment and its corresponding token won't break deployments for other still-live experiments

  • Github's personal access token page will give you a nice summary of how recently you've worked on each of your experiments, and maybe remind you to destroy some and save some money

TLDR you can use the same token for everything and it'll work just fine, but I don't recommend it.

other random notes

I wrote this primarily for me, and in that context it is a huge improvement and helps me get up and running much, much faster --- no need to dig around in documentation. Additionally, I've now documented the exact steps for myself.

Some parts of it, like the Github personal access token, are still annoying, but as far as I'm aware Github don't allow automation of that part. Maybe prompting the user in the terminal would be a better choice there, though, vs. storing it in a file.

No attempt at multiple development branches is made. This is for experiments and proofs-of-concept --- you're probably committing directly to main. In a production context the "run a terraform plan on a feature branch before merging a PR" vibe isn't safe anyway, as there are no measures preventing you using your production deployment credentials from within the context of Terraform's external provider.

license

MIT License

Copyright (c) 2023 John Slee

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.