aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xops/tf-gcs-init/tf-gcs-init.sh113
1 files changed, 113 insertions, 0 deletions
diff --git a/ops/tf-gcs-init/tf-gcs-init.sh b/ops/tf-gcs-init/tf-gcs-init.sh
new file mode 100755
index 0000000..f675381
--- /dev/null
+++ b/ops/tf-gcs-init/tf-gcs-init.sh
@@ -0,0 +1,113 @@
+#!/usr/bin/env bash
+
+# This script creates a bucket in GCS that will be used to store
+# terraform state. It also creates a service account 'terraform' to
+# perform the actions. It ensures the admin of the account can
+# impersonate the 'terraform' service account, so we don't need to
+# generate keys. The roles for the SA are also set.
+
+# TODO:
+# gcloud projects add-iam-policy-binding fcuny-backups --member="serviceAccount:terraform@fcuny-homelab.iam.gserviceaccount.com" --role="roles/viewer"
+# gcloud projects add-iam-policy-binding fcuny-backups
+# --member="serviceAccount:terraform@fcuny-homelab.iam.gserviceaccount.com"
+# --role="roles/owner"
+# I need to perform some actions on all the projects, not just the
+# first one, need to expand the script for that part.
+
+set -u
+set -e
+set -o pipefail
+
+# I'm the admin of the project
+GCP_ADMIN_ACCOUNT="franck.cuny@gmail.com"
+
+# this is the main project that is used for "core" infra
+GCP_PROJECT="fcuny-homelab"
+GCP_PROJECTS="$(gcloud projects list --format 'value(projectId)')"
+GCS_LOCATION="us-west1"
+GCS_BUCKET_NAME="world-tf-state"
+GCP_SERVICE_ACCOUNT_NAME="terraform"
+GCP_SERVICE_ACCOUNT="${GCP_SERVICE_ACCOUNT_NAME}@${GCP_PROJECT}.iam.gserviceaccount.com"
+GCP_SERVICE_ACCOUNT_ROLES=(
+ "roles/editor"
+ "roles/owner"
+)
+
+function bucket:exist() {
+ if gsutil ls gs://${1} &>/dev/null; then
+ true
+ else
+ false
+ fi
+}
+
+function bucket() {
+ if ! bucket:exist "${GCS_BUCKET_NAME}"; then
+ echo "creating GCS bucket $GCS_BUCKET_NAME ..."
+ (
+ set -x
+ gsutil mb -p ${GCP_PROJECT} -l ${GCS_LOCATION} gs://${GCS_BUCKET_NAME}
+ gsutil versioning set on gs://${GCS_BUCKET_NAME}
+ )
+ else
+ echo "GCS bucket $GCS_BUCKET_NAME already created"
+ fi
+}
+
+function service_account:exist() {
+ if gcloud iam service-accounts describe "${1}" &>/dev/null; then
+ true
+ else
+ false
+ fi
+}
+
+function service_account() {
+ if ! service_account:exist "${GCP_SERVICE_ACCOUNT}"; then
+ echo "creating service account ..."
+ (
+ set -x
+ gcloud iam service-accounts create "${GCP_SERVICE_ACCOUNT_NAME}" --display-name="Terraform Service Account"
+ )
+ else
+ echo "service account already created"
+ fi
+}
+
+function service_account:has_role() {
+ [[ $(gcloud projects get-iam-policy ${1} --flatten=bindings --filter="bindings.members=serviceAccount:${2} AND bindings.role=$3" 2>/dev/null | wc -l) -ne 0 ]]
+}
+
+function service_account:admins_token_creator() {
+ [[ $(gcloud --project=${1} iam service-accounts get-iam-policy ${GCP_SERVICE_ACCOUNT} --flatten=bindings --filter="bindings.members=user:${GCP_ADMIN_ACCOUNT} AND bindings.role=roles/iam.serviceAccountTokenCreator" 2>/dev/null | wc -l) -ne 0 ]]
+}
+
+function roles() {
+ for project in $GCP_PROJECTS; do
+ for role in "${GCP_SERVICE_ACCOUNT_ROLES[@]}"; do
+ if ! service_account:has_role "${project}" "${GCP_SERVICE_ACCOUNT}" "${role}" ; then
+ echo "granting ${role##*/} role to service account for project ${project} ..."
+ (
+ set -x
+ gcloud projects add-iam-policy-binding "${project}" --member="serviceAccount:${GCP_SERVICE_ACCOUNT}" --role="${role}"
+ ) 1>/dev/null
+ else
+ echo "service account already has ${role##*/} role for project ${project}"
+ fi
+ done
+
+ if ! service_account:admins_token_creator "${project}" ; then
+ echo "adding AccountTokenCreator role to admin account for project ${project} ..."
+ (
+ set -x
+ gcloud --project="${project}" iam service-accounts add-iam-policy-binding "${GCP_SERVICE_ACCOUNT}" --member user:${GCP_ADMIN_ACCOUNT} --role="roles/iam.serviceAccountTokenCreator"
+ ) 1>/dev/null
+ else
+ echo "admin account has already AccountTokenCreator role for project ${project}"
+ fi
+ done
+}
+
+bucket
+service_account
+roles