| #!/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 |
| # |
| # 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/security/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 |
| # VANADIUM_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 "${VANADIUM_ROOT}" ]]; then |
| echo 'WARNING: VANADIUM_ROOT is not specified, cannot build fresh binaries' |
| return |
| fi |
| local -r REPO_BIN_DIR="${VANADIUM_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" |
| |
| 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 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 |
| 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" --additional_principals="${CREDENTIALS_DIR}" bash --rcfile "${INSTALL_DIR}/rcfile" |
| } |
| |
| main "$@" |