blob: 9802ef3a2cffe902f6ed4cc4e92e5cc6f0aca202 [file] [log] [blame]
#!/bin/bash
# Copyright 2015 The Vanadium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
#
# 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:
#
# # Builds and fetches binaries from local repository
# ./vbash
#
# # Gets binaries from local filesystem
# ./vbash /path/to/binaries
#
# # Gets binaries from HTTP server
# ./vbash http://host/path
#
# # Work with staging environment.
# ./vbash -s
#
# Limitations:
# Tested on goobuntu and OS X 10.9.5.
set -e
readonly BIN_PACKAGES=(v.io/x/ref/cmd/principal v.io/x/ref/services/agent/agentd)
BIN_NAMES=(${BIN_PACKAGES[@]})
for (( i=0; i<${#BIN_PACKAGES[@]}; i++ )); do
BIN_NAMES[$i]=$(basename "${BIN_PACKAGES[$i]}")
done
# 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}"
return 1
fi
}
###############################################################################
# Fetches binaries needed by device manager installation.
# Globals:
# BIN_NAMES
# BIN_PACKAGES
# V23_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 build latest version of the binaries and copy
# them from the repository.
if [[ -z "${BIN_SOURCE}" ]]; then
if [[ -z "${V23_ROOT}" ]]; then
echo 'WARNING: V23_ROOT is not specified, cannot build fresh binaries'
return
fi
local -r REPO_BIN_DIR="${V23_ROOT}/release/go/bin"
echo "Building and Fetching binaries:${bin_names_str} from build repository: ${REPO_BIN_DIR} ..."
for package in "${BIN_PACKAGES[@]}"; do
local bin_name=$(basename "${package}")
v23 go install "${package}" 2> /dev/null || echo "WARNING: Could not build binary: ${bin_name}"
# while the build failed, we still try to see if we can copy the binary from the build repository.
copy_binary "${bin_name}" "${REPO_BIN_DIR}" "${BIN_INSTALL}" || echo "WARNING: Could not copy binary: ${bin_name} from build repository: ${REPO_BIN_DIR}"
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}" || echo "WARNING: Could not copy binary: ${bin_name} from: ${BIN_SOURCE}"
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}") || echo "WARNING: Could not fetch binary: ${bin_name} from HTTP server: ${BIN_SOURCE}/${bin_name}"
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"
# Check staging flag "-s".
local INSTALL_DIR="${HOME}/.vbash"
local IDENTITY_PROVIDER="https://dev.v.io/auth/google"
local NS="/(dev.v.io/role/vprod)@ns.dev.v.io:8101"
local TAG=""
local TITLE="vbash"
while getopts ":s" opt; do
case $opt in
s)
INSTALL_DIR="${HOME}/.vbash-staging"
IDENTITY_PROVIDER="https://dev.staging.v.io/auth/google"
NS="/(dev.v.io/role/vprod)@ns.dev.staging.v.io:8101"
TAG="\[\e[1;35m\][STAGING] "
TITLE="vbash staging"
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
esac
done
shift $(( OPTIND - 1 ))
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 vanadium blessing.
cat <<EOF > "${INSTALL_DIR}/rcfile"
if [[ Darwin == "$(uname)" ]]; then
if [[ -r /etc/profile ]]; then . /etc/profile; fi
for n in ~/.bash_profile ~/.bash_login ~/.profile; do
if [[ -r "$n" ]]; then
. "$n"
break
fi
done
else
if [[ -f ~/.bashrc ]]; then . ~/.bashrc; fi
fi
export PROMPT_COMMAND='PS1="\[\e]0;${TITLE}\007\]\u@\h (${TAG}\[\e[1;32m\]\$("${BIN_INSTALL}/principal" dump -s)\[\e[0m\]):\w \$ "'
export V23_NAMESPACE="${NS}"
export V23_OAUTH_IDENTITY_PROVIDER="${IDENTITY_PROVIDER}"
if [[ "${SEEK_BLESSING}" -eq "1" ]]; then
"${BIN_INSTALL}/principal" seekblessings
fi
EOF
V23_CREDENTIALS="${CREDENTIALS_DIR}" exec "${BIN_INSTALL}/agentd" --additional-principals="${CREDENTIALS_DIR}" bash --rcfile "${INSTALL_DIR}/rcfile"
}
main "$@"