249 lines
8.5 KiB
Bash
Executable File
249 lines
8.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
BIN_DIR=~/bin
|
|
DEFAULT_USER=${CTCTL_USER:-$(whoami | sed -r 's/\@.*//')}
|
|
DEFAULT_DOMAIN=${CTCTL_DOMAIN:-consul}
|
|
|
|
read -p "Enter your user login [${DEFAULT_USER}] " INSTALL_USER
|
|
INSTALL_USER=${INSTALL_USER:-${DEFAULT_USER}}
|
|
read -p "Enter container domain [${DEFAULT_DOMAIN}] " INSTALL_DOMAIN
|
|
INSTALL_DOMAIN=${INSTALL_DOMAIN:-${DEFAULT_DOMAIN}}
|
|
|
|
function get_gh_release() {
|
|
local VERSION
|
|
# Check if cached version file exists and has been modified less than 6 hours ago
|
|
if [[ -e "~/.ctctl/versions/$1" && $(stat -c %Y -- "~/.ctctl/versions/$1") -gt $(($EPOCHSECONDS - 21600)) ]]; then
|
|
VERSION=$(cat ~/.ctctl/versions/$1)
|
|
else
|
|
VERSION=$(curl --silent "https://api.github.com/repos/$1/releases/latest" | \
|
|
jq -r .tag_name | sed -E 's/^v//')
|
|
# Cache the last version so we don't ask github API every time
|
|
mkdir -p $(dirname ~/.ctctl/versions/$1)
|
|
echo -n ${VERSION} > ~/.ctctl/versions/$1
|
|
fi
|
|
echo ${VERSION}
|
|
}
|
|
|
|
# Detect OS
|
|
SYSTEM="$(uname -s)"
|
|
case "${SYSTEM}" in
|
|
Linux*) MACHINE=linux;;
|
|
Darwin*) MACHINE=darwin;;
|
|
*) MACHINE=unknown;;
|
|
esac
|
|
# Architesture, so we support Apple M1/M2 chips
|
|
CPU=$(uname -m)
|
|
case "${ARCH}" in
|
|
x86_64) ARCH=amd64;;
|
|
arm64) ARCH=arm64;;
|
|
*) ARCH=amd64;;
|
|
esac
|
|
|
|
if [ "${MACHINE}" = "unknown" ]; then
|
|
echo "Unsupported system"
|
|
exit 1
|
|
fi
|
|
|
|
# Check that we have the required utilities
|
|
for TOOL in jq openssl curl unzip fzf git; do
|
|
if ! command -v $TOOL > /dev/null 2>&1; then
|
|
echo "$TOOL not found. Please install it first"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
[ -d ${BIN_DIR} ] || mkdir -p ${BIN_DIR}
|
|
|
|
mkdir -p ~/.ctctl/versions
|
|
|
|
# Install hashicorp binaries
|
|
for UTIL in vault consul consul-template nomad levant; do
|
|
|
|
LAST_VER=$(get_gh_release "hashicorp/${UTIL}")
|
|
echo "Last version of ${UTIL} is v${LAST_VER}"
|
|
|
|
if [ -x "${BIN_DIR}/${UTIL}" ]; then
|
|
CUR_VER=$(${BIN_DIR}/${UTIL} --version 2>/dev/null | head -1 | sed -E 's/.* v([0-9]+(\.[0-9]+)*).*/\1/')
|
|
echo "${UTIL} v${CUR_VER} is installed"
|
|
fi
|
|
|
|
if [ ! -x "${BIN_DIR}/${UTIL}" ] || ! echo -e "${LAST_VER}\n${CUR_VER}" | sort --version-sort --check > /dev/null 2>&1; then
|
|
echo "Installing ${UTIL} v${LAST_VER}"
|
|
curl -L -O https://releases.hashicorp.com/${UTIL}/${LAST_VER}/${UTIL}_${LAST_VER}_${MACHINE}_${ARCH}.zip
|
|
unzip -o -d ~/bin/ ${UTIL}_${LAST_VER}_${MACHINE}_${ARCH}.zip
|
|
rm -f ${UTIL}_${LAST_VER}_${MACHINE}_${ARCH}.zip
|
|
else
|
|
echo "Last ${UTIL} version (v${CUR_VER}) is already installed"
|
|
fi
|
|
done
|
|
|
|
## Install logcli
|
|
for UTIL in logcli; do
|
|
LAST_VER=$(get_gh_release "grafana/loki")
|
|
if [ -x "${BIN_DIR}/${UTIL}" ]; then
|
|
CUR_VER=$(${BIN_DIR}/${UTIL} --version 2>&1 | head -1 | sed -E 's/.* version ([0-9]+(\.[0-9]+)*).*/\1/')
|
|
echo "${UTIL} v${CUR_VER} is installed"
|
|
fi
|
|
|
|
if [ ! -x "${BIN_DIR}/${UTIL}" ] || ! echo -e "${LAST_VER}\n${CUR_VER}" | sort --version-sort --check > /dev/null 2>&1; then
|
|
echo "Installing ${UTIL} v${LAST_VER}"
|
|
curl -L -O https://github.com/grafana/loki/releases/download/v${LAST_VER}/logcli-${MACHINE}-${ARCH}.zip
|
|
unzip -o -d ~/bin/ ${UTIL}-${MACHINE}-${ARCH}.zip
|
|
rm -f ${UTIL}-${MACHINE}-${ARCH}.zip
|
|
mv -f ~/bin/logcli-${MACHINE}-${ARCH} ~/bin/logcli
|
|
else
|
|
echo "Last ${UTIL} version (v${CUR_VER}) is already installed"
|
|
fi
|
|
done
|
|
|
|
# Install yq
|
|
for UTIL in yq; do
|
|
LAST_VER=$(get_gh_release "mikefarah/yq")
|
|
if [ -x "${BIN_DIR}/${UTIL}" ]; then
|
|
CUR_VER=$(${BIN_DIR}/${UTIL} --version 2>&1 | sed -E 's/.* version v([0-9]+(\.[0-9]+)*).*/\1/')
|
|
echo "${UTIL} v${CUR_VER} is installed"
|
|
fi
|
|
|
|
if [ ! -x "${BIN_DIR}/${UTIL}" ] || ! echo -e "${LAST_VER}\n${CUR_VER}" | sort --version-sort --check > /dev/null 2>&1; then
|
|
echo "Installing ${UTIL} v${LAST_VER}"
|
|
curl -L -o ${BIN_DIR}/${UTIL} https://github.com/mikefarah/${UTIL}/releases/download/v${LAST_VER}/${UTIL}_${MACHINE}_${ARCH}
|
|
chmod +x ${BIN_DIR}/${UTIL}
|
|
else
|
|
echo "Last ${UTIL} version (v${CUR_VER}) is already installed"
|
|
fi
|
|
done
|
|
|
|
# Install gomplate
|
|
for UTIL in gomplate; do
|
|
LAST_VER=$(get_gh_release "hairyhenderson/${UTIL}")
|
|
if [ -x "${BIN_DIR}/${UTIL}" ]; then
|
|
CUR_VER=$(${BIN_DIR}/${UTIL} --version 2>&1 | sed -E 's/gomplate version ([0-9]+(\.[0-9]+)*)/\1/')
|
|
echo "${UTIL} v${CUR_VER} is installed"
|
|
fi
|
|
|
|
if [ ! -x "${BIN_DIR}/${UTIL}" ] || ! echo -e "${LAST_VER}\n${CUR_VER}" | sort --version-sort --check > /dev/null 2>&1; then
|
|
echo "Installing ${UTIL} v${LAST_VER}"
|
|
curl -L -o ${BIN_DIR}/${UTIL} https://github.com/hairyhenderson/${UTIL}/releases/download/v${LAST_VER}/${UTIL}_${MACHINE}-${ARCH}
|
|
chmod +x ${BIN_DIR}/${UTIL}
|
|
else
|
|
echo "Last ${UTIL} version (v${CUR_VER}) is already installed"
|
|
fi
|
|
done
|
|
|
|
mkdir -p ~/.bashrc.d
|
|
mkdir -p ~/.ctctl/${INSTALL_DOMAIN}
|
|
mkdir -p ~/.ctctl/bin
|
|
|
|
source ~/.bashrc
|
|
|
|
PREV_IFS=$IFS
|
|
DIR_IN_PATH=0
|
|
IFS=":"
|
|
for P in $PATH; do
|
|
[ "$P" = "~/bin" -o "$P" = "$(realpath ~/bin)" ] && DIR_IN_PATH=1
|
|
done
|
|
IFS=$PREV_IFS
|
|
|
|
echo "Configuring the environment"
|
|
echo
|
|
echo "Installing ct env scripts"
|
|
cp -f ctctl ~/.ctctl/bin/
|
|
mkdir -p ~/.local/share/bash-completion/completions
|
|
cp -f bash_completion ~/.local/share/bash-completion/completions/ctctl
|
|
chmod 755 ~/.ctctl/bin/*
|
|
cp -f ctctl.example.conf ~/.ctctl/${INSTALL_DOMAIN}/ctctl.example.conf
|
|
|
|
cat <<_EOF > ~/.ctctl/${INSTALL_DOMAIN}/ctctl.conf
|
|
CTCTL_USER=${INSTALL_USER}
|
|
CTCTL_DOMAIN=${INSTALL_DOMAIN}
|
|
_EOF
|
|
cat << '_EOF' > ~/.local/share/bash-completion/completions/vault
|
|
complete -C ~/bin/vault vault
|
|
_EOF
|
|
cat << '_EOF' > ~/.local/share/bash-completion/completions/nomad
|
|
complete -C ~/bin/nomad nomad
|
|
_EOF
|
|
cat << '_EOF' > ~/.local/share/bash-completion/completions/consul
|
|
complete -C ~/bin/consul consul
|
|
_EOF
|
|
logcli --completion-script-bash > ~/.local/share/bash-completion/completions/logcli
|
|
cat <<_EOF > ~/.bashrc.d/ctctl
|
|
alias ctctl='source ~/.ctctl/bin/ctctl'
|
|
_EOF
|
|
|
|
if [ "${DIR_IN_PATH}" = "0" ]; then
|
|
cat <<_EOF >> ~/.bashrc.d/ctctl
|
|
export PATH=$(realpath ~/bin):$PATH
|
|
_EOF
|
|
source ~/.bashrc.d/ctctl
|
|
fi
|
|
|
|
echo
|
|
echo "Configuring Vault access"
|
|
cat <<_EOF >> ~/.ctctl/${INSTALL_DOMAIN}/ctctl.conf
|
|
VAULT_ADDR=https://active.vault.service.${INSTALL_DOMAIN}:8200
|
|
_EOF
|
|
|
|
echo
|
|
echo "Configuring Nomad access"
|
|
cat <<_EOF >> ~/.ctctl/${INSTALL_DOMAIN}/ctctl.conf
|
|
NOMAD_ADDR=https://nomad.service.${INSTALL_DOMAIN}:4646
|
|
NOMAD_CACERT=~/.ctctl/${INSTALL_DOMAIN}/nomad/ca.crt
|
|
NOMAD_CLIENT_CERT=~/.ctctl/${INSTALL_DOMAIN}/nomad/cli.crt
|
|
NOMAD_CLIENT_KEY=~/.ctctl/${INSTALL_DOMAIN}/nomad/cli.key
|
|
_EOF
|
|
|
|
echo
|
|
echo "Configuring Consul access"
|
|
cat <<_EOF >> ~/.ctctl/${INSTALL_DOMAIN}/ctctl.conf
|
|
CONSUL_HTTP_ADDR=https://consul.service.${INSTALL_DOMAIN}:8501
|
|
CONSUL_CACERT=~/.ctctl/${INSTALL_DOMAIN}/consul/ca.crt
|
|
CONSUL_CLIENT_CERT=~/.ctctl/${INSTALL_DOMAIN}/consul/cli.crt
|
|
CONSUL_CLIENT_KEY=~/.ctctl/${INSTALL_DOMAIN}/consul/cli.key
|
|
_EOF
|
|
|
|
# Install the certificate renewer scripts
|
|
# We'll use consul-template to obtain and renew certificates for Nomad and Consul
|
|
for UTIL in nomad consul; do
|
|
mkdir -p ~/.ctctl/${INSTALL_DOMAIN}/${UTIL}
|
|
# Create the files so realpath doesn't fail
|
|
# Note : on Linux we could use realpath -m, but not on MAC OS
|
|
for FILE in ca.crt cli.crt cli.key cli.p12 bundle.pem; do
|
|
touch ~/.ctctl/${INSTALL_DOMAIN}/${UTIL}/${FILE}
|
|
done
|
|
cat <<_EOF > ~/.ctctl/${INSTALL_DOMAIN}/${UTIL}/bundle.pem.tpl
|
|
{{ with pkiCert "pki/${UTIL}/issue/${UTIL}-user" "common_name=${CTCTL_USER:-$(whoami | sed -r 's/\@.*//')}.${UTIL}.${INSTALL_DOMAIN}" "ttl=8760h" }}
|
|
{{ .CA }}
|
|
{{ .Cert }}
|
|
{{ .Key }}
|
|
{{ .CA | writeToFile "$(realpath ~/.ctctl/${INSTALL_DOMAIN}/${UTIL}/ca.crt)" "" "" "0644" }}
|
|
{{ .Cert | writeToFile "$(realpath ~/.ctctl/${INSTALL_DOMAIN}/${UTIL}/cli.crt)" "" "" "0644" }}
|
|
{{ .Key | writeToFile "$(realpath ~/.ctctl/${INSTALL_DOMAIN}/${UTIL}/cli.key)" "" "" "0600" }}
|
|
{{ end }}
|
|
_EOF
|
|
cat <<_EOF > ~/.ctctl/${INSTALL_DOMAIN}/${UTIL}/consul-template.hcl
|
|
template {
|
|
source = "$(realpath ~/.ctctl/${INSTALL_DOMAIN}/${UTIL}/bundle.pem.tpl)"
|
|
destination = "$(realpath ~/.ctctl/${INSTALL_DOMAIN}/${UTIL}/bundle.pem)"
|
|
perms = 0640
|
|
exec {
|
|
# We create a PKCS12 bundle so we can easily import it in a web browser
|
|
command = "openssl pkcs12 -export -out $(realpath ~/.ctctl/${INSTALL_DOMAIN}/${UTIL}/cli.p12) -in $(realpath ~/.ctctl/${INSTALL_DOMAIN}/${UTIL}/cli.crt) -inkey $(realpath ~/.ctctl/${INSTALL_DOMAIN}/${UTIL}/cli.key) -passout pass:${UTIL}"
|
|
}
|
|
}
|
|
_EOF
|
|
done
|
|
|
|
source ~/.bashrc
|
|
|
|
echo
|
|
echo
|
|
echo ----------------------------------------------------------
|
|
echo Installation done. You can now switch to your new env with
|
|
echo ctctl switch ${INSTALL_DOMAIN}
|
|
echo
|
|
echo Then authenticate using
|
|
echo ctctl auth
|
|
echo
|
|
echo ----------------------------------------------------------
|