#!/bin/bash # # Description: # Helper functions to programmatically provision (e.g. for CIT). # Aliases on these functions are also created so that this script can be # sourced in your shell, in your ~/.bashrc file, etc. and directly called. # # Usage: # Source this file and call the relevant functions. # function ssh_public_key() { echo -e "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDZBgLQts30PYXEMJnCU21QC+1ZE0Sv/Ry48Au3nYXn1KNoW/7C2qQ3KO2ZnpZRHCstFiU8QIlB9edi0cgcAoDWBkCiFBZEORxMvohWtrRQzf+x59o48lVjA/Fn7G+9hmavhLaDf6Qe7OhH8XUshNtnIQIUvNEWXKE75k32wUbuF8ibhJNpOOYKL4tVXK6IIKg6jR88BwGKPY/NZCl/HbhjnDJY0zCU1pZSprN6o/S953y/XXVozkh1772fCNeu4USfbt0oZOEJ57j6EWwEYIJhoeAEMAoD8ELt/bc/5iex8cuarM4Uib2JHO6WPWbBQ0NlrARIOKLrxkjjfGWarOLWBAgvwQn5zLg1pKb7aI4+jbA+ZSrII5B2HuYE9MDlU8NPL4pHrRfapGLkG/Fe9zNPvScXh+9iSWfD6G5ZoISutjiJO/iVYN0QSuj9QEIj9tl20czFz3Dhnq4sPPl5hoLunyQfajY7C/ipv6ilJyrEc0V6Z9FdPhpEI+HOgJr2vDQTFscQuyfWuzGJDZf6zPdZWo2pBql9E7piARuNAjakylGar/ebkCgfy28XQoDbDT0P0VYp+E8W5EYacx+zc5MuNhRTvbsO12fydT8V61MtA78wM/b0059feph+0zTykEHk670mYVoE3erZX+U1/BVBLSV9QzopO6/Pgx2ryriJfQ== weaveworks-cit" } function decrypt() { if [ -z "$1" ]; then echo >&2 "Failed to decode and decrypt $2: no secret key was provided." return 1 fi # Set md5 because existing keys were encrypted that way and openssl default changed echo "$3" | openssl base64 -d | openssl enc -md md5 -d -aes256 -pass "pass:$1" } function ssh_private_key() { # The private key has been AES256-encrypted and then Base64-encoded using the following command: # $ openssl enc -in /tmp/weaveworks_cit_id_rsa -e -aes256 -pass stdin | openssl base64 > /tmp/weaveworks_cit_id_rsa.aes.b64 # The below command does the reverse, i.e. base64-decode and AES-decrypt the file, and prints it to stdout. # N.B.: Ask the password to Marc, or otherwise re-generate the SSH key using: # $ ssh-keygen -t rsa -b 4096 -C "weaveworks-cit" decrypt "$1" "SSH private key" "$( cat <&2 "Failed to decode and decrypt SSH private key: no secret key was provided." return 1 fi local ssh_private_key_path="$HOME/.ssh/weaveworks_cit_id_rsa" [ -e "$ssh_private_key_path" ] && rm -f "$ssh_private_key_path" ssh_private_key "$1" >"$ssh_private_key_path" chmod 400 "$ssh_private_key_path" echo "$ssh_private_key_path" } function gcp_credentials() { # The below GCP service account JSON credentials have been AES256-encrypted and then Base64-encoded using the following command: # $ openssl enc -in ~/.ssh/weaveworks-cit.json -e -aes256 -pass stdin | openssl base64 > /tmp/weaveworks-cit.json.aes.b64 # The below command does the reverse, i.e. base64-decode and AES-decrypt the file, and prints it to stdout. # N.B.: Ask the password to Marc, or otherwise re-generate the credentials for GCP, as per ../tools/provisioning/gcp/README.md. decrypt "$1" "JSON credentials" "$( cat <&2 "Failed to configure for Digital Ocean: no value for the SECRET_KEY environment variable." return 1 fi # SSH public key: export TF_VAR_do_public_key_path="$HOME/.ssh/weaveworks_cit_id_rsa.pub" ssh_public_key >"$TF_VAR_do_public_key_path" export DIGITALOCEAN_SSH_KEY_NAME="weaveworks-cit" export TF_VAR_do_public_key_id=5228799 # SSH private key: export TF_VAR_do_private_key_path=$(set_up_ssh_private_key "$SECRET_KEY") # API token: # The below Digital Ocean token has been AES256-encrypted and then Base64-encoded using the following command: # $ openssl enc -in /tmp/digital_ocean_token.txt -e -aes256 -pass stdin | openssl base64 > /tmp/digital_ocean_token.txt.aes.b64 # The below command does the reverse, i.e. base64-decode and AES-decrypt the file, and prints it to stdout. # N.B.: Ask the password to Marc, or otherwise re-generate the token for Digital Ocean, as per ../tools/provisioning/do/README.md. export DIGITALOCEAN_TOKEN=$(decrypt "$SECRET_KEY" "Digital Ocean token" "U2FsdGVkX1/Gq5Rj9dDDraME8xK30JOyJ9dhfQzPBaaePJHqDPIG6of71DdJW0UyFUyRtbRflCPaZ8Um1pDJpU5LoNWQk4uCApC8+xciltT73uQtttLBG8FqgFBvYIHS") export DIGITALOCEAN_TOKEN_NAME="weaveworks-cit" export TF_VAR_client_ip=$(curl -s -X GET http://checkip.amazonaws.com/) } alias do_on='do_on' function do_off() { unset TF_VAR_do_public_key_path unset DIGITALOCEAN_SSH_KEY_NAME unset TF_VAR_do_public_key_id unset TF_VAR_do_private_key_path unset DIGITALOCEAN_TOKEN unset DIGITALOCEAN_TOKEN_NAME unset TF_VAR_client_ip } alias do_off='do_off' # shellcheck disable=2155 function gcp_on() { # Set up everything required to run tests on GCP. # Steps from ../tools/provisioning/gcp/README.md have been followed. # All sensitive files have been encrypted, see respective functions. if [ -z "$SECRET_KEY" ]; then echo >&2 "Failed to configure for Google Cloud Platform: no value for the SECRET_KEY environment variable." return 1 fi # SSH public key and SSH username: export TF_VAR_gcp_public_key_path="$HOME/.ssh/weaveworks_cit_id_rsa.pub" ssh_public_key >"$TF_VAR_gcp_public_key_path" export TF_VAR_gcp_username=$(cut -d' ' -f3 "$TF_VAR_gcp_public_key_path" | cut -d'@' -f1) # SSH private key: export TF_VAR_gcp_private_key_path=$(set_up_ssh_private_key "$SECRET_KEY") # JSON credentials: export GOOGLE_CREDENTIALS_FILE="$HOME/.ssh/weaveworks-cit.json" [ -e "$GOOGLE_CREDENTIALS_FILE" ] && rm -f "$GOOGLE_CREDENTIALS_FILE" gcp_credentials "$SECRET_KEY" >"$GOOGLE_CREDENTIALS_FILE" chmod 400 "$GOOGLE_CREDENTIALS_FILE" export GOOGLE_CREDENTIALS=$(cat "$GOOGLE_CREDENTIALS_FILE") export TF_VAR_client_ip=$(curl -s -X GET http://checkip.amazonaws.com/) export TF_VAR_gcp_project="${PROJECT:-"weave-net-tests"}" # shellcheck disable=2015 [ -z "$PROJECT" ] && echo >&2 "WARNING: no value provided for PROJECT environment variable: defaulted it to $TF_VAR_gcp_project." || true } alias gcp_on='gcp_on' function gcp_off() { unset TF_VAR_gcp_public_key_path unset TF_VAR_gcp_username unset TF_VAR_gcp_private_key_path unset GOOGLE_CREDENTIALS_FILE unset GOOGLE_CREDENTIALS unset TF_VAR_client_ip unset TF_VAR_gcp_project } alias gcp_off='gcp_off' # shellcheck disable=2155 function aws_on() { # Set up everything required to run tests on Amazon Web Services. # Steps from ../tools/provisioning/aws/README.md have been followed. # All sensitive files have been encrypted, see respective functions. if [ -z "$SECRET_KEY" ]; then echo >&2 "Failed to configure for Amazon Web Services: no value for the SECRET_KEY environment variable." return 1 fi # SSH public key: export TF_VAR_aws_public_key_name="weaveworks_cit_id_rsa" # SSH private key: export TF_VAR_aws_private_key_path=$(set_up_ssh_private_key "$SECRET_KEY") # The below AWS access key ID and secret access key have been AES256-encrypted and then Base64-encoded using the following commands: # $ openssl enc -in /tmp/aws_access_key_id.txt -e -aes256 -pass stdin | openssl base64 > /tmp/aws_access_key_id.txt.aes.b64 # $ openssl enc -in /tmp/aws_secret_access_key.txt -e -aes256 -pass stdin | openssl base64 > /tmp/aws_secret_access_key.txt.aes.b64 # The below commands do the reverse, i.e. base64-decode and AES-decrypt the encrypted and encoded strings, and print it to stdout. # N.B.: Ask the password to Marc, or otherwise re-generate the AWS access key ID and secret access key, as per ../tools/provisioning/aws/README.md. export AWS_ACCESS_KEY_ID="$(decrypt "$SECRET_KEY" "AWS access key ID" "U2FsdGVkX18Txjm2PWSlJsToYm1vv4dMTtVLkRNiQbrC6Y6GuIHb1ao5MmGPJ1wf")" export AWS_SECRET_ACCESS_KEY="$(decrypt "$SECRET_KEY" "AWS secret access key" "$( cat <&2 <<-EOF ERROR: $1 Usage: \$ tf_ssh [OPTION]... Examples: \$ tf_ssh 1 \$ tf_ssh 1 -o LogLevel VERBOSE \$ tf_ssh 1 -i ~/.ssh/custom_private_key_id_rsa Available machines: EOF cat -n >&2 <<<"$(terraform output public_etc_hosts)" } # shellcheck disable=SC2155 function tf_ssh() { [ -z "$1" ] && tf_ssh_usage "No host ID provided." && return 1 local ip="$(sed "$1q;d" <<<"$(terraform output public_etc_hosts)" | cut -d ' ' -f 1)" shift # Drop the first argument, corresponding to the machine ID, to allow passing other arguments to SSH using "$@" -- see below. [ -z "$ip" ] && tf_ssh_usage "Invalid host ID provided." && return 1 # shellcheck disable=SC2029 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$@" "$(terraform output username)@$ip" } alias tf_ssh='tf_ssh' function tf_ansi_usage() { cat >&2 <<-EOF ERROR: $1 Usage: \$ tf_ansi [OPTION]... Examples: \$ tf_ansi setup_weave-net_dev \$ tf_ansi 1 \$ tf_ansi 1 -vvv --private-key=~/.ssh/custom_private_key_id_rsa \$ tf_ansi setup_weave-kube --extra-vars "docker_version=1.12.6 kubernetes_version=1.5.6" Available playbooks: EOF cat -n >&2 <<<"$(for file in "$(dirname "${BASH_SOURCE[0]}")"/../../config_management/*.yml; do basename "$file" | sed 's/.yml//'; done)" } # shellcheck disable=SC2155,SC2064 function tf_ansi() { [ -z "$1" ] && tf_ansi_usage "No Ansible playbook provided." && return 1 local id="$1" shift # Drop the first argument to allow passing other arguments to Ansible using "$@" -- see below. if [[ "$id" =~ ^[0-9]+$ ]]; then local playbooks=(../../config_management/*.yml) local path="${playbooks[(($id - 1))]}" # Select the ith entry in the list of playbooks (0-based). else local path="$(dirname "${BASH_SOURCE[0]}")/../../config_management/$id.yml" fi local inventory="$(mktemp /tmp/ansible_inventory_XXX)" trap 'rm -f $inventory' SIGINT SIGTERM RETURN echo -e "$(terraform output ansible_inventory)" >"$inventory" [ ! -r "$path" ] && tf_ansi_usage "Ansible playbook not found: $path" && return 1 ansible-playbook "$@" -u "$(terraform output username)" -i "$inventory" --ssh-extra-args="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" "$path" } alias tf_ansi='tf_ansi'