diff --git a/startupscript/butane/idle-shutdown.sh b/startupscript/butane/idle-shutdown.sh index 6ec52eb7..3964453e 100644 --- a/startupscript/butane/idle-shutdown.sh +++ b/startupscript/butane/idle-shutdown.sh @@ -38,11 +38,17 @@ readonly LAST_BOOT_TIME # Get the last time the VM was active. Default to 0 if not set. LAST_ACTIVE="$(get_guest_attribute "last-active/cpu" "0")" LAST_ACTIVE_PROXY="$(get_guest_attribute "last-active/proxy" "0")" +LAST_ACTIVE_SSH="$(get_guest_attribute "last-active/ssh" "0")" -# get the latest time between the two last active timestamps +# get the latest active timestamps if (( LAST_ACTIVE < LAST_ACTIVE_PROXY )); then LAST_ACTIVE="${LAST_ACTIVE_PROXY}" fi + +if (( LAST_ACTIVE < LAST_ACTIVE_SSH )); then + LAST_ACTIVE="${LAST_ACTIVE_SSH}" +fi + # get the latest time between the last boot time and the last active time. The last active timestamp could still be really old when the VM is rebooted and # the last active timestamp is not updated yet. if (( LAST_ACTIVE < LAST_BOOT_TIME )); then diff --git a/startupscript/butane/probe-user-access.sh b/startupscript/butane/probe-user-access.sh index 2467f44d..acadd182 100644 --- a/startupscript/butane/probe-user-access.sh +++ b/startupscript/butane/probe-user-access.sh @@ -39,3 +39,10 @@ else NOW="$(date +'%s')" set_metadata "last-active/cpu" "${NOW}" fi + +if ps auxwww | grep sshd-session | grep -v grep | grep '@'; then + echo "Detect an active ssh session" + NOW="$(date +'%s')" + set_metadata "last-active/ssh" "${NOW}" +fi + diff --git a/startupscript/dataproc/startup.sh b/startupscript/dataproc/startup.sh old mode 100644 new mode 100755 index 9c3c0ca2..1e435015 --- a/startupscript/dataproc/startup.sh +++ b/startupscript/dataproc/startup.sh @@ -197,21 +197,47 @@ function set_guest_attributes() { # Map the CLI server to appropriate service path function get_service_url() { case "$1" in - "verily") echo "https://terra-$2.api.verily.com" ;; - "verily-devel") echo "https://terra-devel-$2.api.verily.com" ;; - "verily-autopush") echo "https://terra-autopush-$2.api.verily.com" ;; - "verily-staging") echo "https://terra-staging-$2.api.verily.com" ;; - "verily-preprod") echo "https://terra-preprod-$2.api.verily.com" ;; - "dev-stable") echo "https://workbench-dev.verily.com/api/$2" ;; - "dev-unstable") echo "https://workbench-dev-unstable.verily.com/api/$2" ;; - "test") echo "https://workbench-test.verily.com/api/$2" ;; - "staging") echo "https://workbench-staging.verily.com/api/$2" ;; - "prod") echo "https://workbench-prod.verily.com/api/$2" ;; - *) return 1 ;; + "verily") echo "https://workbench.verily.com/api/$2" ;; + "dev-stable") echo "https://workbench-dev.verily.com/api/$2" ;; + "dev-unstable") echo "https://workbench-dev-unstable.verily.com/api/$2" ;; + "test") echo "https://workbench-test.verily.com/api/$2" ;; + "staging") echo "https://workbench-staging.verily.com/api/$2" ;; + "prod") echo "https://workbench.verily.com/api/$2" ;; + *) return 1 ;; esac } readonly -f get_service_url +# Get the app proxy url for the env. +function get_app_proxy_uri() { + local env="${1}" + case "${env}" in + "verily") + env="prod" + ;; + "dev-stable") + env="dev" + ;; + esac + echo "workbench-app-${env}.verily.com" +} +readonly -f get_app_proxy_uri + +# Get workbench frontend url +function get_ui_uri() { + local env="${1}" + if [[ "${env}" == "verily" || "${env}" == "prod" ]]; then + echo "https://workbench.verily.com" + elif [[ "${env}" == "dev-stable" ]]; then + echo "https://workbench-dev.verily.com" + elif [[ "${env}" == "dev-unstable" || "${env}" == "test" || "${env}" == "staging" ]]; then + echo "https://workbench-${env}.verily.com" + else + echo "https://workbench.verily.com" + fi +} +readonly -f get_ui_uri + # If the script exits without error let the UI know it completed successfully # Otherwise if an error occurred write the line and command that failed to guest attributes. function exit_handler { @@ -267,7 +293,7 @@ function install_nextflow() { readonly -f install_nextflow ####################################### -### Begin environment setup +### Begin environment setup ####################################### # Let the UI know the script has started @@ -601,7 +627,7 @@ EOF emit "Setting up git integration..." -# Create the user SSH directory +# Create the user SSH directory ${RUN_AS_LOGIN_USER} "mkdir -p ${USER_SSH_DIR} --mode 0700" # Get the user's SSH key from Workbench, and if set, write it to the user's .ssh directory @@ -802,25 +828,75 @@ IS_NON_GOOGLE_ACCOUNT="$(curl "${USER_SERVICE_URL}/api/profile?path=non_google_a | jq '.value')" readonly IS_NON_GOOGLE_ACCOUNT -APP_PROXY="" -if [[ "${IS_NON_GOOGLE_ACCOUNT}" == "true" ]]; then +ENABLE_VWB_PROXY="$(get_metadata_value "instance/attributes/enable-dataproc-vwb-proxy")" +readonly ENABLE_VWB_PROXY +# Retrieve Workbench proxy agent image +PROXY_AGENT_IMAGE="$(get_metadata_value "instance/attributes/proxy-agent-image")" +readonly PROXY_AGENT_IMAGE +APP_PROXY="$(get_app_proxy_uri "${TERRA_SERVER}")" +readonly APP_PROXY +RESOURCE_ID="$(get_metadata_value "instance/attributes/terra-resource-id")" +readonly RESOURCE_ID +# Retrieve app proxy user facing URL +APP_PROXY_URL="https://${RESOURCE_ID}.${APP_PROXY}" +readonly APP_PROXY_URL +# Retrieve app proxy service facing URL +PROXY_SERVICE_URL="$(get_service_url "${TERRA_SERVER}" "proxy")/" +readonly PROXY_SERVICE_URL + +# Define constants for proxy types +PROXY_TYPE_VWB="VWB_PROXY" +PROXY_TYPE_GOOGLE="GOOGLE_PROXY" +PROXY_TYPE_GOOGLE_AGENT_WITH_VWB_PROXY="GOOGLE_AGENT_WITH_VWB_PROXY" + +# Decide proxy type +PROXY_TYPE="" +if [[ ${ENABLE_VWB_PROXY} == "true" && -n "${PROXY_AGENT_IMAGE}" ]]; then + PROXY_TYPE="${PROXY_TYPE_VWB}" +elif [[ ${IS_NON_GOOGLE_ACCOUNT} == "true" ]]; then + PROXY_TYPE="${PROXY_TYPE_GOOGLE_AGENT_WITH_VWB_PROXY}" +else + PROXY_TYPE="${PROXY_TYPE_GOOGLE}" +fi + +if [[ "${PROXY_TYPE}" != "${PROXY_TYPE_GOOGLE}" ]]; then ################################### # Start workbench app proxy agent ################################### + if [[ "${PROXY_TYPE}" == "${PROXY_TYPE_VWB}" ]]; then + emit "Using Workbench Proxy" + ENABLE_MONITORING_SCRIPT="$(get_metadata_value "instance/attributes/enable-dataproc-monitoring-script")" + readonly ENABLE_MONITORING_SCRIPT - APP_PROXY="$(get_metadata_value "instance/attributes/terra-app-proxy")" - readonly APP_PROXY - if [[ -n "${APP_PROXY}" ]]; then - emit "Using custom Proxy Agent" - RESOURCE_ID="$(get_metadata_value "instance/attributes/terra-resource-id")" - NEW_PROXY="https://${APP_PROXY}" - NEW_PROXY_URL="${RESOURCE_ID}.${APP_PROXY}" - readonly RESOURCE_ID - readonly NEW_PROXY - readonly NEW_PROXY_URL - - # Create a systemd service to start the workbench app proxy. - cat << EOF > "${WORKBENCH_PROXY_AGENT_SERVICE}" + cat <"${WORKBENCH_PROXY_AGENT_SERVICE}" +[Unit] +Description=Workbench Docker Proxy Agent +After=docker.service +Requires=docker.service + +[Service] +ExecStartPre=/bin/bash -c 'while [ ! -f ${PROXY_AGENT_BANNER} ]; do sleep 5; done' +ExecStart=/bin/bash -c '/usr/bin/docker run \\ + --detach \\ + --name "proxy-agent" \\ + --restart=unless-stopped \\ + --net=host "${PROXY_AGENT_IMAGE}" \\ + --proxy="${PROXY_SERVICE_URL}" \\ + --host="localhost:8123" \\ + --compute-platform="GCP" \\ + --shim-path="websocket-shim" \\ + --rewrite-websocket-host="true" \\ + --backend="${RESOURCE_ID}" \\ + --session-cookie-name="_xsrf" \\ + --inject-banner="\$(cat ${PROXY_AGENT_BANNER})" \\ + --enable-monitoring-script="${ENABLE_MONITORING_SCRIPT:-false}"' + +[Install] +WantedBy=multi-user.target +EOF + else + emit "Using Google Proxy Agent with Workbench Proxy" + cat <"${WORKBENCH_PROXY_AGENT_SERVICE}" [Unit] Description=Workbench App Proxy Agent Service @@ -831,13 +907,16 @@ Restart=on-failure [Install] WantedBy=multi-user.target EOF + fi # Enable and start the workbench app proxy agent service systemctl daemon-reload systemctl enable "${WORKBENCH_PROXY_AGENT_SERVICE_NAME}" - systemctl start "${WORKBENCH_PROXY_AGENT_SERVICE_NAME}" + # Start the service in non-blocking mode to allow startup script to continue without waiting + systemctl --no-block start "${WORKBENCH_PROXY_AGENT_SERVICE_NAME}" emit "Workbench Proxy Agent service started" - fi +else + emit "Using Google Proxy" fi ################################### @@ -1048,24 +1127,13 @@ fi emit "Starting Hail install script..." ${RUN_PYTHON} ${HAIL_SCRIPT_PATH} fi - + if [[ "${IS_NON_GOOGLE_ACCOUNT}" == "false" ]]; then ###################################################### # Configure the original (non-workbench) proxy agent ###################################################### emit "Configuring the original Proxy Agent banner for Google account..." - # Map the CLI server to the appropriate UI url - if [[ "${TERRA_SERVER}" == *"verily"* ]]; then - # Map the CLI server to the appropriate UI url - if [[ "${TERRA_SERVER}" == "verily" ]]; then - UI_BASE_URL="workbench.verily.com" - else - UI_BASE_URL="${TERRA_SERVER/verily/terra}-ui-terra.api.verily.com" - fi - else - >&2 echo "ERROR: ${TERRA_SERVER} is not a known verily server." - exit 1 - fi + UI_BASE_URL=$(get_ui_uri "${TERRA_SERVER}") readonly UI_BASE_URL # The banner.html file contains