about summary refs log tree commit diff
path: root/ops/tf-gcs-init/tf-gcs-init.sh
diff options
context:
space:
mode:
Diffstat (limited to 'ops/tf-gcs-init/tf-gcs-init.sh')
-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