Skip to content

Instantly share code, notes, and snippets.

@tomasbasham
Created May 22, 2023 23:07
Show Gist options
  • Save tomasbasham/81fb328f0797a98d864da75f4246827d to your computer and use it in GitHub Desktop.
Save tomasbasham/81fb328f0797a98d864da75f4246827d to your computer and use it in GitHub Desktop.

Revisions

  1. tomasbasham created this gist May 22, 2023.
    168 changes: 168 additions & 0 deletions bootstrap
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,168 @@
    #!/usr/bin/env bash

    set -eou pipefail

    if [[ "${TRACE-0}" == "1" ]]; then
    set -o xtrace
    fi

    COMMAND=${0##*/}
    DIRNAME=$(dirname "$0")

    usage() {
    echo "
    $COMMAND --organisation=ORGANISATION
    --organisation-id=ORGANISATION_ID
    --billing-account-id=BILLING_ACCOUNT_ID
    Setup a terraform Admin project on Google Cloud Platform
    --organisation
    Organisation name to associate with Google Cloud Resources.
    --organisation-id
    Organisation ID to associate with Google Cloud Resources.
    --billing-account-id
    Billing account ID to associate with Google Cloud Resources.
    " >&2
    exit 2
    }

    if [[ "$#" -eq 0 ]]; then
    usage
    fi

    organisation=""
    organisation_id=""
    billing_account_id=""

    while true; do
    case $# in
    0) break;;
    esac
    case $1 in
    --organisation)
    shift
    case $# in
    0)
    echo "$COMMAND: --organisation: ORGANISATION argument expected." >&2
    exit 1
    ;;
    esac
    organisation=$1
    ;;
    --organisation=*)
    organisation=${1#*=}
    ;;
    --organisation-id)
    shift
    case $# in
    0)
    echo "$COMMAND: --organisation-id: ORGANISATION_ID argument expected." >&2
    exit 1
    ;;
    esac
    organisation_id=$1
    ;;
    --organisation-id=*)
    organisation_id=${1#*=}
    ;;
    --billing-account-id)
    shift
    case $# in
    0)
    echo "$COMMAND: --billing-account-id: BILLING_ACCOUNT_ID argument expected." >&2
    exit 1
    ;;
    esac
    billing_account_id=$1
    ;;
    --billing-account-id=*)
    billing_account_id=${1#*=}
    ;;
    *)
    usage
    ;;
    esac
    shift
    done

    # Validate required variables.

    [[ -z $organisation ]] && echo "$COMMAND --organisation is required" && exit 1
    [[ -z $organisation_id ]] && echo "$COMMAND --organisation-id is required" && exit 1
    [[ -z $billing_account_id ]] && echo "$COMMAND --billing-account-id is required" && exit 1

    tf_admin=${organisation}-terraform-admin
    tf_creds=${HOME}/.config/gcloud/${tf_admin}.json
    tf_service_account=terraform@${tf_admin}.iam.gserviceaccount.com

    echo "An administrative project will be created with the following details:
    Organisation: ${organisation}
    Organisation ID: ${organisation_id}
    Billing Account: ${billing_account_id}
    Terraform Admin Project: ${tf_admin}
    Terraform Admin Service Account: ${tf_service_account}
    "
    read -p "Continue? [N/y]: " -n 1 -r
    echo
    echo
    if ! [[ $REPLY =~ ^[Yy]$ ]]; then
    exit 0
    fi

    # Create a Terraform admin project and link it to a billing account.

    gcloud projects create ${tf_admin} \
    --organization ${organisation_id} \
    --set-as-default

    gcloud beta billing projects link ${tf_admin} \
    --billing-account ${billing_account_id}

    # Create a Terraform service account in the Terraform admin project and
    # download the JSON credentials.

    gcloud iam service-accounts create terraform \
    --display-name "Terraform admin account"

    gcloud iam service-accounts keys create ${tf_creds} \
    --iam-account ${tf_service_account}

    # Grant the service account permission to create service accounts for the admin
    # project.

    gcloud projects add-iam-policy-binding ${tf_admin} \
    --member serviceAccount:${tf_service_account} \
    --role roles/iam.serviceAccountCreator

    # Grant the service account permission to manage workload identity pools.

    gcloud projects add-iam-policy-binding ${tf_admin} \
    --member serviceAccount:${tf_service_account} \
    --role roles/iam.workloadIdentityPoolAdmin

    # Grant the service account permission to create projects and assign billing
    # accounts.

    gcloud organizations add-iam-policy-binding ${organisations_id} \
    --member serviceAccount:${tf_service_account} \
    --role roles/resourcemanager.projectCreator

    gcloud organizations add-iam-policy-binding ${organisation_id} \
    --member serviceAccount:${tf_service_account} \
    --role roles/billing.user

    echo "An administrative project was successfully created. You have been set as
    the project owner but are likely to want to remove this in future. You can
    access the project here:
    https://console.cloud.google.com/home/dashboard?project=${tf_admin}
    The service account credentials have been downloaded to:
    ${tf_creds}
    "