Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 1 | #!/bin/bash |
| 2 | # |
| 3 | # Installs node manager on the local machine. |
| 4 | # |
| 5 | # Specifically: |
| 6 | # |
| 7 | # 1. Fetches the binaries required for a node manager installation from a few |
| 8 | # possible sources. |
| 9 | # |
| 10 | # 2. Sets up the helper with setuid. The helper binary needs to be owned by |
| 11 | # root and have the suid bit set, to enable the node manager to run binaries |
| 12 | # under different system accounts than itself. |
| 13 | # |
| 14 | # 3. Runs the self-install command on the node manager. |
| 15 | # |
| 16 | # Usage: |
| 17 | # |
Bogdan Caprita | 99d45cc | 2014-10-30 10:16:25 -0700 | [diff] [blame] | 18 | # # Gets binaries from local repository |
Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 19 | # ./nminstall <install parent dir> |
| 20 | # |
| 21 | # # Gets binaries from local filesystem |
| 22 | # ./nminstall <install parent dir> /path/to/binaries |
| 23 | # |
Bogdan Caprita | 7f85cfa | 2014-11-04 11:08:03 -0800 | [diff] [blame] | 24 | # # Gets binaries from HTTP server |
Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 25 | # ./nminstall <install parent dir> http://host/path |
| 26 | |
| 27 | set -e |
| 28 | |
| 29 | usage() { |
| 30 | echo "usage:" |
| 31 | echo "./nminstall <install parent dir> [<binary source>]" |
| 32 | } |
| 33 | |
Bogdan Caprita | d174846 | 2014-11-08 16:49:46 -0800 | [diff] [blame] | 34 | readonly BIN_NAMES=(noded suidhelper agentd) |
Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 35 | |
Bogdan Caprita | 99d45cc | 2014-10-30 10:16:25 -0700 | [diff] [blame] | 36 | ############################################################################### |
| 37 | # Copies one binary from source to destination. |
| 38 | # Arguments: |
| 39 | # name of the binary |
| 40 | # source dir of binary |
| 41 | # destination dir of binary |
| 42 | # Returns: |
| 43 | # None |
| 44 | ############################################################################### |
| 45 | copy_binary() { |
| 46 | local -r BIN_NAME="$1" |
| 47 | local -r BIN_SRC_DIR="$2" |
| 48 | local -r BIN_DEST_DIR="$3" |
| 49 | local -r SOURCE="${BIN_SRC_DIR}/${BIN_NAME}" |
| 50 | if [[ -x "${SOURCE}" ]]; then |
| 51 | local -r DESTINATION="${BIN_DEST_DIR}/${BIN_NAME}" |
| 52 | cp "${SOURCE}" "${DESTINATION}" |
| 53 | chmod 700 "${DESTINATION}" |
| 54 | else |
| 55 | echo "couldn't find ${SOURCE}" |
| 56 | exit 1 |
| 57 | fi |
| 58 | } |
| 59 | |
| 60 | ############################################################################### |
Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 61 | # Fetches binaries needed by node manager installation. |
| 62 | # Globals: |
| 63 | # BIN_NAMES |
| 64 | # VEYRON_ROOT |
| 65 | # Arguments: |
| 66 | # destination for binaries |
| 67 | # source of binaries |
| 68 | # Returns: |
| 69 | # None |
Bogdan Caprita | 99d45cc | 2014-10-30 10:16:25 -0700 | [diff] [blame] | 70 | ############################################################################### |
Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 71 | get_binaries() { |
| 72 | local -r BIN_INSTALL="$1" |
| 73 | local -r BIN_SOURCE="$2" |
| 74 | |
| 75 | local bin_names_str="" |
Bogdan Caprita | 7f85cfa | 2014-11-04 11:08:03 -0800 | [diff] [blame] | 76 | for bin_name in "${BIN_NAMES[@]}"; do |
Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 77 | bin_names_str+=" ${bin_name}" |
| 78 | done |
Bogdan Caprita | 7f85cfa | 2014-11-04 11:08:03 -0800 | [diff] [blame] | 79 | |
Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 80 | # If source is not specified, try to look for it in the repository. |
| 81 | if [[ -z "${BIN_SOURCE}" ]]; then |
| 82 | if [[ -z "${VEYRON_ROOT}" ]]; then |
| 83 | echo 'ERROR: binary source not specified and no local repository available' |
| 84 | exit 1 |
| 85 | fi |
| 86 | local -r REPO_BIN_DIR="${VEYRON_ROOT}/veyron/go/bin" |
Bogdan Caprita | 99d45cc | 2014-10-30 10:16:25 -0700 | [diff] [blame] | 87 | echo "Fetching binaries:${bin_names_str} from build repository: ${REPO_BIN_DIR} ..." |
Bogdan Caprita | 7f85cfa | 2014-11-04 11:08:03 -0800 | [diff] [blame] | 88 | for bin_name in "${BIN_NAMES[@]}"; do |
Bogdan Caprita | 99d45cc | 2014-10-30 10:16:25 -0700 | [diff] [blame] | 89 | copy_binary "${bin_name}" "${REPO_BIN_DIR}" "${BIN_INSTALL}" |
Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 90 | done |
Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 91 | return |
| 92 | fi |
| 93 | |
Bogdan Caprita | 99d45cc | 2014-10-30 10:16:25 -0700 | [diff] [blame] | 94 | # If the source is specified as an existing local filesystem path, |
| 95 | # look for the binaries there. |
| 96 | if [[ -d "${BIN_SOURCE}" ]]; then |
| 97 | echo "Fetching binaries:${bin_names_str} locally from: ${BIN_SOURCE} ..." |
Bogdan Caprita | 7f85cfa | 2014-11-04 11:08:03 -0800 | [diff] [blame] | 98 | for bin_name in "${BIN_NAMES[@]}"; do |
Bogdan Caprita | 99d45cc | 2014-10-30 10:16:25 -0700 | [diff] [blame] | 99 | copy_binary "${bin_name}" "${BIN_SOURCE}" "${BIN_INSTALL}" |
| 100 | done |
| 101 | return |
| 102 | fi |
| 103 | |
Bogdan Caprita | 7f85cfa | 2014-11-04 11:08:03 -0800 | [diff] [blame] | 104 | # If the source looks like a URL, use HTTP to fetch. |
| 105 | local -r URL_REGEXP='^(https?|ftp|file)://' |
| 106 | if [[ "${BIN_SOURCE}" =~ ${URL_REGEXP} ]]; then |
| 107 | echo "Fetching binaries:${bin_names_str} remotely from: ${BIN_SOURCE} ..." |
| 108 | for bin_name in "${BIN_NAMES[@]}"; do |
| 109 | local DEST="${BIN_INSTALL}/${bin_name}" |
| 110 | curl -f -o "${DEST}" "${BIN_SOURCE}/${bin_name}" |
| 111 | chmod 700 "${DEST}" |
| 112 | done |
| 113 | return |
| 114 | fi |
| 115 | |
Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 116 | echo 'ERROR: couldn'"'"'t fetch binaries.' |
| 117 | exit 1 |
| 118 | } |
| 119 | |
| 120 | main() { |
| 121 | local -r INSTALL_PARENT_DIR="$1" |
| 122 | if [[ -z "${INSTALL_PARENT_DIR}" ]]; then |
| 123 | echo 'No local install destination specified!' |
| 124 | usage |
| 125 | exit 1 |
| 126 | fi |
| 127 | |
| 128 | if [[ ! -d "${INSTALL_PARENT_DIR}" ]]; then |
| 129 | echo "${INSTALL_PARENT_DIR} is not a directory!" |
| 130 | exit 1 |
| 131 | fi |
| 132 | |
| 133 | local -r INSTALL_DIR="${INSTALL_PARENT_DIR}/node_manager" |
| 134 | |
| 135 | # TODO(caprita): Check that the node manager is not already installed before |
| 136 | # proceeding. We should require an explicit uninstall to avoid wiping away |
| 137 | # the node manager accidentally. |
| 138 | sudo rm -rf "${INSTALL_DIR}" |
| 139 | mkdir -m 700 "${INSTALL_DIR}" |
| 140 | |
| 141 | local -r BIN_INSTALL="${INSTALL_DIR}/bin" |
| 142 | mkdir -m 700 "${BIN_INSTALL}" |
| 143 | |
| 144 | # Fetch the binaries. |
| 145 | local -r BIN_SOURCE="$2" |
| 146 | get_binaries "${BIN_INSTALL}" "${BIN_SOURCE}" |
Bogdan Caprita | 7f85cfa | 2014-11-04 11:08:03 -0800 | [diff] [blame] | 147 | for bin_name in "${BIN_NAMES[@]}"; do |
| 148 | local BINARY="${BIN_INSTALL}/${bin_name}" |
| 149 | if [[ ! -s "${BINARY}" ]]; then |
| 150 | echo "${BINARY} is empty." |
| 151 | exit 1 |
| 152 | fi |
| 153 | done |
Bogdan Caprita | 99d45cc | 2014-10-30 10:16:25 -0700 | [diff] [blame] | 154 | echo "Binaries are in ${BIN_INSTALL}." |
Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 155 | |
| 156 | # Set up the suidhelper. |
| 157 | echo "Configuring suidhelper ..." |
| 158 | local -r SETUID_SCRIPT="${BIN_INSTALL}/suidhelper" |
| 159 | sudo bash -c "chown root:root \"${SETUID_SCRIPT}\"; chmod 4551 \"${SETUID_SCRIPT}\"" |
| 160 | echo "Suidhelper configured." |
| 161 | |
| 162 | # Tell the node manager to install itself. |
| 163 | local -r NM_ROOT="${INSTALL_DIR}/nmroot" |
| 164 | echo "Installing node manager under ${NM_ROOT} ..." |
Bogdan Caprita | d174846 | 2014-11-08 16:49:46 -0800 | [diff] [blame] | 165 | local -r PUBLISH=$(hostname) |
Bogdan Caprita | e20f8d4 | 2014-11-12 11:32:29 -0800 | [diff] [blame] | 166 | VEYRON_NM_CURRENT="${INSTALL_DIR}/noded.curr" VEYRON_NM_ROOT="${NM_ROOT}" VEYRON_NM_HELPER="${SETUID_SCRIPT}" "${BIN_INSTALL}/noded" --install_self --name="${PUBLISH}" |
Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 167 | echo "Node manager installed." |
Bogdan Caprita | e20f8d4 | 2014-11-12 11:32:29 -0800 | [diff] [blame] | 168 | |
| 169 | local -r SECURITY_DIR="${INSTALL_DIR}/security" |
| 170 | mkdir -m 700 "${SECURITY_DIR}" |
| 171 | local -r PRINCIPAL_DIR="${SECURITY_DIR}/principal" |
| 172 | mkdir -m 700 "${PRINCIPAL_DIR}" |
| 173 | local -r AGENT_KEY_DIR="${SECURITY_DIR}/keys" |
| 174 | mkdir -m 700 "${AGENT_KEY_DIR}" |
| 175 | |
| 176 | # Run node manager under the security agent. |
| 177 | echo |
| 178 | echo "Running:" |
| 179 | echo "VEYRON_CREDENTIALS=\"${PRINCIPAL_DIR}\" \"${BIN_INSTALL}/agentd\" --additional_principals=\"${AGENT_KEY_DIR}\" \"${INSTALL_DIR}/noded.curr\"" |
| 180 | echo |
| 181 | # NOTE: If you update the command below, please also update the command echoed |
| 182 | # above to keep the two in sync. |
| 183 | VEYRON_CREDENTIALS="${PRINCIPAL_DIR}" "${BIN_INSTALL}/agentd" --additional_principals="${AGENT_KEY_DIR}" "${INSTALL_DIR}/noded.curr" |
Bogdan Caprita | 151ee8d | 2014-10-29 16:37:33 -0700 | [diff] [blame] | 184 | } |
| 185 | |
| 186 | main "$@" |