diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..725f06f54 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +.PHONY: lint + +lint: + shellcheck scripts/* diff --git a/scripts/gen-root-ca b/scripts/gen-root-ca index 511edc61c..3d6b9758a 100755 --- a/scripts/gen-root-ca +++ b/scripts/gen-root-ca @@ -19,6 +19,7 @@ DIR="$(dirname "${CMD}")" CN="$1" OUT="$(realpath "${2:-.}")" +# shellcheck source=scripts/ssl-common.sh source "${DIR}/ssl-common.sh" # Create a secret key and CA file for the self-signed CA diff --git a/scripts/gen-root-cert b/scripts/gen-root-cert index 13005f07c..17b95aedf 100755 --- a/scripts/gen-root-cert +++ b/scripts/gen-root-cert @@ -19,6 +19,7 @@ DIR="$(dirname "${CMD}")" CN="$1" OUT="$(realpath "${2:-.}")" +# shellcheck source=scripts/ssl-common.sh source "${DIR}/ssl-common.sh" # generate default CSR and sign (root + wildcard) diff --git a/scripts/gen-token-auth-cert b/scripts/gen-token-auth-cert index 8bf9857d4..b927fa6e1 100755 --- a/scripts/gen-token-auth-cert +++ b/scripts/gen-token-auth-cert @@ -19,10 +19,12 @@ DIR="$(dirname "${CMD}")" CN="$1" OUT="$(realpath "${2:-.}")" +# shellcheck source=scripts/ssl-common.sh source "${DIR}/ssl-common.sh" keyid() { - local der="$(openssl ec -in "$1" -pubout -outform DER 2>/dev/null)" + local der + der="$(openssl ec -in "$1" -pubout -outform DER 2>/dev/null)" python -c "import sys as S; from base64 import b32encode as B; import hashlib as H; h = H.sha256(); h.update(S.argv[1].encode('ascii')); s = B(h.digest()[:30]).decode('ascii'); S.stdout.write(':'.join([s[i:i+4] for i in range(0, len(s), 4)]))" "${der}" } diff --git a/scripts/gen-vpn-certs b/scripts/gen-vpn-certs index 82609e601..fa133a9fa 100755 --- a/scripts/gen-vpn-certs +++ b/scripts/gen-vpn-certs @@ -19,6 +19,7 @@ DIR="$(dirname "${CMD}")" CN="$1" OUT="$(realpath "${2:-.}")" +# shellcheck source=scripts/ssl-common.sh source "${DIR}/ssl-common.sh" VPN_PKI="$(realpath "${OUT}/vpn")" diff --git a/scripts/patch-hosts b/scripts/patch-hosts index b79e6a6fd..8b03cc58c 100755 --- a/scripts/patch-hosts +++ b/scripts/patch-hosts @@ -1,11 +1,4 @@ -#!/bin/sh - -set -e - -CMD=$0 -DIR=$(dirname "$CMD") - -DOMAIN=$1 +#!/bin/bash -eu SERVICES="api registry vpn db" SERVICES="${SERVICES} img devices" # FIXME: remove @@ -17,20 +10,23 @@ usage() { echo } -if [ -z "$DOMAIN" ]; then +if [ -z "$1" ]; then usage exit 1 fi +DOMAIN="$1" + # We need sudo to write to /etc/hosts, so first write to a temp file and then # append all entries to hosts file. -tmp=$(mktemp --tmpdir openbalena.XXXX) +tmp="$(mktemp --tmpdir openbalena.XXXX)" for service in $SERVICES; do name="${service}.${DOMAIN}" - if ! grep "\s$name" /etc/hosts >/dev/null 2>&1 ; then + if ! grep "\\s$name" /etc/hosts >/dev/null 2>&1 ; then echo "adding $name" - echo "127.0.0.1 $name" >>$tmp + echo "127.0.0.1 $name" >>"${tmp}" fi done -cat $tmp | sudo tee -a /etc/hosts >/dev/null -rm -f $tmp +# shellcheck disable=SC2024 +sudo tee -a /etc/hosts >/dev/null <"${tmp}" +rm -f "${tmp}" diff --git a/scripts/run-fig-command b/scripts/run-fig-command index fa8ec1528..edf8446a8 100755 --- a/scripts/run-fig-command +++ b/scripts/run-fig-command @@ -1,13 +1,11 @@ -#!/bin/sh +#!/bin/bash -eu -set -e - -CMD=$0 -DIR=$(dirname "$CMD") -BASE_DIR=$(dirname "$DIR") +CMD="$0" +DIR="$(dirname "$CMD")" +BASE_DIR="$(dirname "$DIR")" echo_bold() { - printf "\033[1m%s\033[0m\n" "$@" + printf "\\033[1m%s\\033[0m\\n" "$@" } PROJECT_FILE="${BASE_DIR}/.project" @@ -16,16 +14,17 @@ if [ ! -f "$PROJECT_FILE" ]; then echo_bold 'See README.md for help.' exit 1 fi -PROJECT=$(cat "$PROJECT_FILE") +PROJECT="$(cat "$PROJECT_FILE")" if [ ! -f "${PROJECT}/activate" ]; then echo_bold 'No project activated. Please create or select an existing one first.' echo_bold 'See README.md for help.' exit 1 fi -PROJECT_NAME=$(basename "$PROJECT") +PROJECT_NAME="$(basename "$PROJECT")" -. "${PROJECT}/activate"; docker-compose \ - --project-name $PROJECT_NAME \ +# shellcheck source=/dev/null +source "${PROJECT}/activate"; docker-compose \ + --project-name "${PROJECT_NAME}" \ -f "${BASE_DIR}/compose/services.yml" \ -f "${PROJECT}/docker-compose.yml" \ "$@" \ No newline at end of file diff --git a/scripts/select-project b/scripts/select-project index 451f1193a..e582b2a85 100755 --- a/scripts/select-project +++ b/scripts/select-project @@ -1,11 +1,8 @@ -#!/bin/sh +#!/bin/bash -eu -set -e - -CMD=$0 -DIR=$(dirname "$CMD") -BASE_DIR=$(dirname "$DIR") -PROJECT_PATH="$1" +CMD="$0" +DIR="$(dirname "$CMD")" +BASE_DIR="$(dirname "$DIR")" usage() { echo "usage: $0 PROJECT_PATH" @@ -14,12 +11,13 @@ usage() { echo } -if [ -z "$PROJECT_PATH" ]; then +if [ -z "$1" ]; then usage exit 1 fi -PROJECT_DIR=$(realpath "$PROJECT_PATH") +PROJECT_PATH="$1" +PROJECT_DIR="$(realpath "$PROJECT_PATH")" if [ ! -d "$PROJECT_DIR" ]; then echo 'Project path refers to a directory that does not exist.' @@ -27,8 +25,8 @@ if [ ! -d "$PROJECT_DIR" ]; then fi if [ ! -f "${PROJECT_DIR}/activate" ]; then - echo 'Project path refers to a directory that is not a valid porject.' + echo 'Project path refers to a directory that is not a valid project.' exit 1 fi -echo -n $PROJECT_DIR >"${BASE_DIR}/.project" +echo -n "${PROJECT_DIR}" >"${BASE_DIR}/.project" diff --git a/scripts/ssl-common.sh b/scripts/ssl-common.sh index 0bf2633ff..d06c60da4 100644 --- a/scripts/ssl-common.sh +++ b/scripts/ssl-common.sh @@ -1,4 +1,5 @@ #!/bin/bash -eu +# shellcheck disable=SC2034 # ensure we have `easyrsa` available if [ -z "${easyrsa_bin-}" ] || [ ! -x "${easyrsa_bin}" ]; then @@ -8,6 +9,7 @@ if [ -z "${easyrsa_bin-}" ] || [ ! -x "${easyrsa_bin}" ]; then easyrsa_url="https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.5/EasyRSA-nix-3.0.5.tgz" (cd "${easyrsa_dir}"; curl -sL "${easyrsa_url}" | tar xz --strip-components=1) easyrsa_bin="${easyrsa_dir}/easyrsa" + # shellcheck disable=SC2064 trap "rm -rf \"${easyrsa_dir}\"" EXIT fi export EASYRSA_BATCH=1 diff --git a/scripts/start-project b/scripts/start-project index b05089c9d..2a0ef4517 100755 --- a/scripts/start-project +++ b/scripts/start-project @@ -7,14 +7,28 @@ BASE_DIR=$(dirname "$DIR") PROJECT_NAME=demo DOMAIN=openbalena.local +usage() { + echo "usage: $0 [-h] [-p] [-n PROJECT_NAME] [-d DOMAIN]" + echo + echo " -p patch hosts - patch the host /etc/hosts file" + echo " PROJECT_NAME a name for the deployment, eg. staging. Default is 'demo'" + echo " DOMAIN the domain name this deployment will run as, eg. example.com. Default is 'openbalena.local'" + echo +} + show_help=false patch_hosts=false while getopts ":hpn:d:" opt; do case "${opt}" in h) show_help=true;; p) patch_hosts=true;; - P) PROJECT_NAME="${OPTARG}";; - H) DOMAIN="${OPTARG}";; + n) PROJECT_NAME="${OPTARG}";; + d) DOMAIN="${OPTARG}";; + *) + echo "Invalid argument: -${OPTARG}" + usage + exit 1 + ;; esac done shift $((OPTIND-1)) @@ -22,22 +36,13 @@ shift $((OPTIND-1)) PROJECT_DIR="$(pwd)/${PROJECT_NAME}" CERTS_DIR="${PROJECT_DIR}/certs" -usage() { - echo "usage: $0 [-h] [-p] [-n PROJECT_NAME] [-d DOMAIN]" - echo - echo " -p patch hosts - patch the host /etc/hosts file" - echo " PROJECT_NAME a name for the deployment, eg. staging. Default is 'demo'" - echo " DOMAIN the domain name this deployment will run as, eg. example.com. Default is 'openbalena.local'" - echo -} - if [ "$show_help" = "true" ]; then usage exit 1 fi echo_bold() { - printf "\033[1m%s\033[0m\n" "${@}" + printf "\\033[1m%s\\033[0m\\n" "${@}" } if [ -d "$PROJECT_DIR" ]; then @@ -49,27 +54,33 @@ echo_bold "==> Creating new project at: $PROJECT_DIR" mkdir -p "$PROJECT_DIR" "$CERTS_DIR" echo_bold "==> Generating root CA cert..." +# shellcheck source=scripts/gen-root-ca source "${DIR}/gen-root-ca" "${DOMAIN}" "${CERTS_DIR}" echo_bold "==> Generating root cert chain for haproxy..." +# shellcheck source=scripts/gen-root-cert source "${DIR}/gen-root-cert" "${DOMAIN}" "${CERTS_DIR}" echo_bold "==> Generating token auth cert..." +# shellcheck source=scripts/gen-token-auth-cert source "${DIR}/gen-token-auth-cert" "${DOMAIN}" "${CERTS_DIR}" echo_bold "==> Generating VPN CA, cert and dhparam (this may take a while)..." +# shellcheck source=scripts/gen-vpn-certs source "${DIR}/gen-vpn-certs" "${DOMAIN}" "${CERTS_DIR}" echo_bold "==> Setting up environment..." +# shellcheck source=scripts/make-env cat >"${PROJECT_DIR}/activate" <(source "${DIR}/make-env") echo_bold "==> Adding default compose file..." cp "${BASE_DIR}/compose/template.yml" "${PROJECT_DIR}/docker-compose.yml" if [ "${patch_hosts}" = "true" ]; then - echo_bold "==> Patching /etc/hosts..." - source "${DIR}/patch-hosts" "${DOMAIN}" + echo_bold "==> Patching /etc/hosts..." + # shellcheck source=scripts/patch-hosts + source "${DIR}/patch-hosts" "${DOMAIN}" fi echo_bold "==> Activating project..." -"${DIR}/select-project" "${PROJECT_DIR}" \ No newline at end of file +"${DIR}/select-project" "${PROJECT_DIR}"