Skip to content

Instantly share code, notes, and snippets.

@hongkongkiwi
Last active November 16, 2023 23:38
Show Gist options
  • Save hongkongkiwi/6198cc254f4bb0ef8df33a9850ac7bc0 to your computer and use it in GitHub Desktop.
Save hongkongkiwi/6198cc254f4bb0ef8df33a9850ac7bc0 to your computer and use it in GitHub Desktop.
Initialises Terraform HTTP backend to Gitlab. Here's a nice script which will ask for details in an interactive way.
# More information can be found at https://docs.gitlab.com/ee/user/infrastructure/#gitlab-managed-terraform-state
terraform {
backend "http" {
}
}
#!/bin/bash
check_password() {
security find-generic-password \
-s "$1" > /dev/null 2>&1 && return 0 || return 1
}
get_username() {
[ -z "$1" ] && { echo >&2 "get_password(): Service name required1"; return 1; }
check_password "$1" || { echo >&2 "get_password(): No password found!"; return 1; }
security find-generic-password \
-D "application password" -s "$1" -g 2>&1 | grep "\"acct\"<blob>=" | cut -d '=' -f2 | cut -d '"' -f2
}
get_password() {
[ -z "$1" ] && { echo >&2 "get_password(): Service name required1"; return 1; }
check_password "$1" || { echo >&2 "get_password(): No password found!"; return 1; }
security find-generic-password \
-D "application password" -s "$1" -g 2>&1 | grep "password: " | cut -d '"' -f2
}
set_password() {
[ -z "$1" ] && { echo >&2 "set_password(): Service name required1"; return 1; }
[ -z "$2" ] && { echo >&2 "set_password(): Username required1"; return 1; }
[ -z "$3" ] && { echo >&2 "set_password(): Password required1"; return 1; }
security add-generic-password \
-s "$1" \
-a "$2" \
-w "$3" \
-j "Gitlab Terraform Setup Script Access token" \
-D "application password" \
-U
}
ask_user_details() {
while read -p "Gitlab Username [$INPUT_TF_USERNAME]: " TF_USERNAME; do
if [ -z "$INPUT_TF_USERNAME" ] && [ -z "$TF_USERNAME" ]; then
echo "ERROR: gitlab Username cannot be empty!"
continue
elif [ -z $INPUT_TF_USERNAME ] && [ ! -z $TF_USERNAME ]; then
INPUT_TF_USERNAME="$TF_USERNAME"
break
elif [ ! -z $INPUT_TF_USERNAME ] && [ -z $TF_USERNAME ]; then
TF_USERNAME="$INPUT_TF_USERNAME"
break
elif [ ! -z $INPUT_TF_USERNAME ] && [ ! -z $TF_USERNAME ]; then
INPUT_TF_USERNAME="$TF_USERNAME"
break
fi
done
while read -p "Access Token [$INPUT_TF_ACCESS_TOKEN]: " TF_ACCESS_TOKEN; do
if [ -z "$INPUT_TF_ACCESS_TOKEN" ] && [ -z "$TF_ACCESS_TOKEN" ]; then
echo "ERROR: Access Token cannot be empty!"
continue
elif [ -z $INPUT_TF_ACCESS_TOKEN ] && [ ! -z $TF_ACCESS_TOKEN ]; then
INPUT_TF_ACCESS_TOKEN="$TF_ACCESS_TOKEN"
break
elif [ ! -z $INPUT_TF_ACCESS_TOKEN ] && [ -z $TF_ACCESS_TOKEN ]; then
TF_ACCESS_TOKEN="$INPUT_TF_ACCESS_TOKEN"
break
elif [ ! -z $INPUT_TF_ACCESS_TOKEN ] && [ ! -z $TF_ACCESS_TOKEN ]; then
INPUT_TF_ACCESS_TOKEN="$TF_ACCESS_TOKEN"
break
fi
done
while read -p "Project ID [$INPUT_PROJECT_ID]: " TF_PROJECT_ID; do
if [ -z "$INPUT_PROJECT_ID" ] && [ -z "$TF_PROJECT_ID" ]; then
echo "ERROR: Project ID cannot be empty!"
continue
else
if [[ ! $TF_PROJECT_ID =~ ^[0-9]+$ ]] && [[ ! $INPUT_PROJECT_ID =~ ^[0-9]+$ ]]; then
echo "ERROR: Project ID can only contain digits!"
continue
elif [ -z $INPUT_PROJECT_ID ] && [ ! -z $TF_PROJECT_ID ]; then
INPUT_PROJECT_ID="$TF_PROJECT_ID"
break
elif [ ! -z $INPUT_PROJECT_ID ] && [ -z $TF_PROJECT_ID ]; then
TF_PROJECT_ID="$INPUT_PROJECT_ID"
break
elif [ ! -z $INPUT_PROJECT_ID ] && [ ! -z $TF_PROJECT_ID ]; then
INPUT_PROJECT_ID="$TF_PROJECT_ID"
break
fi
fi
done
}
ask_state_name() {
while read -p "Terraform State Name [$INPUT_TF_STATE_NAME]: " TF_STATE_NAME; do
if [ -z "$INPUT_TF_STATE_NAME" ] && [ -z "$TF_STATE_NAME" ]; then
echo "ERROR: State name cannot be empty!"
continue
elif [ -z $INPUT_TF_STATE_NAME ] && [ ! -z $TF_STATE_NAME ]; then
INPUT_TF_STATE_NAME="$TF_STATE_NAME"
break
elif [ ! -z $INPUT_TF_STATE_NAME ] && [ -z $TF_STATE_NAME ]; then
TF_STATE_NAME="$INPUT_TF_STATE_NAME"
break
elif [ ! -z $INPUT_TF_ACCESS_TOKEN ] && [ ! -z $TF_STATE_NAME ]; then
INPUT_TF_STATE_NAME="$TF_STATE_NAME"
break
fi
done
}
check_access_token() {
request_cmd="$(curl -i -o - --silent -X GET --header "Accept: application/json" --header "PRIVATE-TOKEN: $1" "https://gitlab.com/api/v4/projects")"
http_status=$(echo "$request_cmd" | grep HTTP | awk '{print $2}')
if [ $http_status -ge 200 ] && [ $http_status -le 299 ]; then
return 0
else
return $http_status
fi
}
get_project_details() {
HTTP_RESPONSE="$(curl --write-out "\nHTTPSTATUS:%{http_code}" --silent -X GET --header "Accept: application/json" --header "PRIVATE-TOKEN: $1" "https://gitlab.com/api/v4/projects/$2")"
HTTP_STATUS=$(echo $HTTP_RESPONSE | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
if [ $HTTP_STATUS -ge 200 ] && [ $HTTP_STATUS -le 299 ]; then
echo "$HTTP_RESPONSE" | sed -e 's/^HTTPSTATUS\:.*//g'
return 0
else
return $HTTP_STATUS
fi
}
INPUT_TF_USERNAME="${GITLAB_USERNAME:-"$1"}"
INPUT_TF_ACCESS_TOKEN="${GITLAB_ACCESS_TOKEN:-"$2"}"
INPUT_PROJECT_ID="$3"
INPUT_TF_STATE_NAME="$4"
if [ -z "$INPUT_TF_ACCESS_TOKEN" ]; then
if check_password "gitlab"; then
INPUT_TF_ACCESS_TOKEN=`get_password "gitlab"`
SAVED_TF_ACCESS_TOKEN="$INPUT_TF_ACCESS_TOKEN"
fi
fi
if [ -z "$INPUT_TF_USERNAME" ]; then
if check_password "gitlab"; then
INPUT_TF_USERNAME=`get_username "gitlab"`
SAVED_TF_USERNAME="$INPUT_TF_USERNAME"
fi
fi
DETAILS_CORRECT=""
PROJECT_DETAILS=""
while true; do
ask_user_details
check_access_token "$TF_ACCESS_TOKEN" || { echo >&2 "ERROR: Invalid Access Token"; continue; }
PROJECT_DETAILS=`get_project_details "$TF_ACCESS_TOKEN" "$TF_PROJECT_ID"` || { echo >&2 "ERROR: Invalid Project ID"; continue; }
[ -z $INPUT_TF_STATE_NAME ] && INPUT_TF_STATE_NAME="`echo "$PROJECT_DETAILS" | jq -r '.name'`-dev"
ask_state_name
read -p "Are these details correct? [Yn]: " -n 1 -r DETAILS_CORRECT
[ -z $DETAILS_CORRECT ] && DETAILS_CORRECT="y"
if [[ $DETAILS_CORRECT =~ ^[Yy]$ ]]; then
printf "\n"
break
else
printf "\n"
fi
done
if [[ ( "$SAVED_TF_USERNAME" != "$TF_USERNAME" && -z "$GITLAB_USERNAME" ) ||
( "$SAVED_TF_ACCESS_TOKEN" != "$TF_ACCESS_TOKEN" && -z "$GITLAB_ACCESS_TOKEN" ) ]]; then
read -p "Saved Gitlab Username or Access Token has changed. Update keychain? [Y]: " -n 1 -r ANSWER
if [[ ! $ANSWER =~ ^[Nn]$ ]]; then
set_password "gitlab" "$TF_USERNAME" "$TF_ACCESS_TOKEN"
fi
echo ""
fi
TF_ADDRESS="https://gitlab.com/api/v4/projects/${TF_PROJECT_ID}/terraform/state/${TF_STATE_NAME}"
echo "Now initailising repo..."
[ -d "$PWD/.terraform" ] && rm -Rf "$PWD/.terraform"
echo terraform init \
-backend-config="address=${TF_ADDRESS}" \
-backend-config="lock_address=${TF_ADDRESS}/lock" \
-backend-config="unlock_address=${TF_ADDRESS}/lock" \
-backend-config="username=${TF_USERNAME}" \
-backend-config="password=${TF_ACCESS_TOKEN}" \
-backend-config="lock_method=POST" \
-backend-config="unlock_method=DELETE" \
-backend-config="retry_wait_min=5"
@spham
Copy link

spham commented Nov 16, 2023

thank you very much

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment