veyron/tools/mgmt/vbash: rename vsh to vbash to avoid conflict with tunnel client.
Change-Id: I65e1a1e4c74d467485178fb1637276dfcc5bdd0b
diff --git a/tools/mgmt/vbash b/tools/mgmt/vbash
new file mode 100755
index 0000000..9a04701
--- /dev/null
+++ b/tools/mgmt/vbash
@@ -0,0 +1,182 @@
+#!/bin/bash
+#
+# Starts up a shell running under the security agent.
+#
+# Specifically:
+#
+# 1. Fetches the binaries needed to set up the security environment. If it
+# can't fetch fresh binaries, it issues a warning but proceeds with existing
+# binaries, if any.
+#
+# 2. Starts a shell under the agent, optionally fetching a remote blessing if
+# the principal is missing.
+#
+# Uses ~/.vbash to store its files, including binaries and the principal.
+#
+# Usage:
+#
+# # Gets binaries from local repository
+# ./vbash
+#
+# # Gets binaries from local filesystem
+# ./vbash /path/to/binaries
+#
+# # Gets binaries from HTTP server
+# ./vbash http://host/path
+#
+# Limitations:
+# This only works on Linux and was only tested on goobuntu.
+# TODO(caprita): Make it work on Mac.
+set -e
+
+readonly BIN_NAMES=(principal agentd)
+
+# TODO(caprita): share copy_binaries and get_binaries with nminstall.
+
+###############################################################################
+# Copies one binary from source to destination.
+# Arguments:
+# name of the binary
+# source dir of binary
+# destination dir of binary
+# Returns:
+# None
+###############################################################################
+copy_binary() {
+ local -r BIN_NAME="$1"
+ local -r BIN_SRC_DIR="$2"
+ local -r BIN_DEST_DIR="$3"
+ local -r SOURCE="${BIN_SRC_DIR}/${BIN_NAME}"
+ if [[ -x "${SOURCE}" ]]; then
+ local -r DESTINATION="${BIN_DEST_DIR}/${BIN_NAME}"
+ cp "${SOURCE}" "${DESTINATION}"
+ chmod 700 "${DESTINATION}"
+ else
+ echo "couldn't find ${SOURCE}"
+ exit 1
+ fi
+}
+
+###############################################################################
+# Fetches binaries needed by node manager installation.
+# Globals:
+# BIN_NAMES
+# VEYRON_ROOT
+# Arguments:
+# destination for binaries
+# source of binaries
+# Returns:
+# None
+###############################################################################
+get_binaries() {
+ local -r BIN_INSTALL="$1"
+ local -r BIN_SOURCE="$2"
+
+ local bin_names_str=""
+ for bin_name in "${BIN_NAMES[@]}"; do
+ bin_names_str+=" ${bin_name}"
+ done
+
+ # If source is not specified, try to look for it in the repository.
+ if [[ -z "${BIN_SOURCE}" ]]; then
+ if [[ -z "${VEYRON_ROOT}" ]]; then
+ echo 'ERROR: binary source not specified and no local repository available'
+ exit 1
+ fi
+ local -r REPO_BIN_DIR="${VEYRON_ROOT}/veyron/go/bin"
+ echo "Fetching binaries:${bin_names_str} from build repository: ${REPO_BIN_DIR} ..."
+ for bin_name in "${BIN_NAMES[@]}"; do
+ copy_binary "${bin_name}" "${REPO_BIN_DIR}" "${BIN_INSTALL}"
+ done
+ return
+ fi
+
+ # If the source is specified as an existing local filesystem path,
+ # look for the binaries there.
+ if [[ -d "${BIN_SOURCE}" ]]; then
+ echo "Fetching binaries:${bin_names_str} locally from: ${BIN_SOURCE} ..."
+ for bin_name in "${BIN_NAMES[@]}"; do
+ copy_binary "${bin_name}" "${BIN_SOURCE}" "${BIN_INSTALL}"
+ done
+ return
+ fi
+
+ # If the source looks like a URL, use HTTP to fetch.
+ local -r URL_REGEXP='^(https?|ftp|file)://'
+ if [[ "${BIN_SOURCE}" =~ ${URL_REGEXP} ]]; then
+ echo "Fetching binaries:${bin_names_str} remotely from: ${BIN_SOURCE} ..."
+ for bin_name in "${BIN_NAMES[@]}"; do
+ local DEST="${BIN_INSTALL}/${bin_name}"
+ curl -f -o "${DEST}" "${BIN_SOURCE}/${bin_name}"
+ chmod 700 "${DEST}"
+ done
+ return
+ fi
+
+ echo "WARNING: couldn't fetch binaries."
+}
+
+main() {
+ if [[ ! -z "${VBASH_INDICATOR}" ]]; then
+ echo "Disallowing running VBASH within VBASH."
+ echo "https://memegen.googleplex.com/5551020600983552"
+ exit 1
+ fi
+ export VBASH_INDICATOR="1"
+
+ local -r INSTALL_DIR="${HOME}/.vbash"
+ if [[ ! -e "${INSTALL_DIR}" ]]; then
+ mkdir -m 700 "${INSTALL_DIR}"
+ fi
+ if [[ ! -d "${INSTALL_DIR}" ]]; then
+ echo "${INSTALL_DIR} is not a directory!"
+ exit 1
+ fi
+
+ local -r BIN_INSTALL="${INSTALL_DIR}/bin"
+ if [[ ! -e "${BIN_INSTALL}" ]]; then
+ mkdir -m 700 "${BIN_INSTALL}"
+ fi
+ if [[ ! -d "${BIN_INSTALL}" ]]; then
+ echo "${BIN_INSTALL} is not a directory!"
+ exit 1
+ fi
+
+ # Fetch the binaries.
+ local -r BIN_SOURCE="$1"
+ get_binaries "${BIN_INSTALL}" "${BIN_SOURCE}"
+ for bin_name in "${BIN_NAMES[@]}"; do
+ local BINARY="${BIN_INSTALL}/${bin_name}"
+ if [[ ! -s "${BINARY}" ]]; then
+ echo "${BINARY} is empty."
+ exit 1
+ fi
+ done
+ echo "Using binaries in ${BIN_INSTALL}."
+
+ # Set up the script to be run by the agent. It first optionally seeks a
+ # blessing, and then runs an interactive shell.
+
+ local -r CREDENTIALS_DIR="${INSTALL_DIR}/principal"
+ if [[ ! -d "${CREDENTIALS_DIR}" ]]; then
+ SEEK_BLESSING="1"
+ fi
+
+ # Use a custom rcfile to optionally get a blessing and also to modify the
+ # shell prompt to include the default veyron blessing.
+ cat <<EOF > "${INSTALL_DIR}/rcfile"
+if [ -f ~/.bashrc ]; then . ~/.bashrc; fi
+if [[ "${SEEK_BLESSING}" -eq "1" ]]; then
+ "${BIN_INSTALL}/principal" seekblessings
+fi
+GREENBOLD="\[\033[1;32m\]"
+default_blessing() {
+ "${BIN_INSTALL}/principal" dump | grep "Default blessings" | sed -e 's/Default blessings: //'
+}
+export PS1="\${PS1}(\${GREENBOLD}\$(default_blessing)\[\033[0m\])$ "
+EOF
+
+VEYRON_CREDENTIALS="${CREDENTIALS_DIR}" exec "${BIN_INSTALL}/agentd" bash --rcfile "${INSTALL_DIR}/rcfile"
+}
+
+main "$@"