diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fb2982e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 P3TERX + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8ed2c62 --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +# SSH to GitHub Actions + +This GitHub Action offers you connect to GitHub Actions VM via SSH for interactive debugging + +## Features + +- Support Ubuntu and macOS +- Provides two optional SSH connection methods, tmate and ngrok +- Proceed to the next step to stay connected +- Send SSH connection info to Telegram + +## Usage + +### Connect to Github Actions VM via SSH by using [tmate](https://tmate.io) + +```yaml +- name: Start SSH via tmate + uses: P3TERX/ssh2actions@main + # Send connection info to Telegram (optional) + # You can find related documents here: https://core.telegram.org/bots + env: + TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} + TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} +``` + +### Connect to Github Actions VM via SSH by using [ngrok](https://ngrok.com) + +```yaml +- name: Start SSH via ngrok + uses: P3TERX/ssh2actions@main + with: + mode: ngrok + env: + # After sign up on the https://ngrok.com + # You can find this token here: https://dashboard.ngrok.com/auth/your-authtoken + NGROK_TOKEN: ${{ secrets.NGROK_TOKEN }} + + # ngrok server region [us, eu, au, ap, sa, jp, in] (optional, default: us) + # You can find this server region here: https://ngrok.com/docs#global-locations + NGROK_REGION: us + + # This password you will use when authorizing via SSH + SSH_PASSWORD: ${{ secrets.SSH_PASSWORD }} + + # Send connection info to Telegram (optional) + # You can find related documents here: https://core.telegram.org/bots + TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} + TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} +``` + +## Lisence + +[MIT](https://github.com/P3TERX/ssh2actions/blob/main/LICENSE) © P3TERX diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..a41e62e --- /dev/null +++ b/action.yml @@ -0,0 +1,16 @@ +name: 'SSH to GitHub Actions' +author: 'P3TERX' +description: 'Connect to GitHub Actions VM via SSH for interactive debugging' +inputs: + mode: + description: 'choose tmate or ngrok mode' + required: false + default: 'tmate' +runs: + using: "composite" + steps: + - run: $GITHUB_ACTION_PATH/${{ inputs.mode }}2actions.sh + shell: bash +branding: + icon: 'terminal' + color: 'gray-dark' diff --git a/ngrok2actions.sh b/ngrok2actions.sh new file mode 100755 index 0000000..c36fa2a --- /dev/null +++ b/ngrok2actions.sh @@ -0,0 +1,133 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2020 P3TERX +# +# This is free software, licensed under the MIT License. +# See /LICENSE for more information. +# +# https://github.com/P3TERX/ssh2actions +# File name:ngrok2actions.sh +# Description: Connect to Github Actions VM via SSH by using ngrok +# Version: 2.0 +# + +Green_font_prefix="\033[32m" +Red_font_prefix="\033[31m" +Green_background_prefix="\033[42;37m" +Red_background_prefix="\033[41;37m" +Font_color_suffix="\033[0m" +INFO="[${Green_font_prefix}INFO${Font_color_suffix}]" +ERROR="[${Red_font_prefix}ERROR${Font_color_suffix}]" +LOG_FILE='/tmp/ngrok.log' +TELEGRAM_LOG="/tmp/telegram.log" +CONTINUE_FILE="/tmp/continue" + +if [[ -z "${NGROK_TOKEN}" ]]; then + echo -e "${ERROR} Please set 'NGROK_TOKEN' environment variable." + exit 2 +fi + +if [[ -z "${SSH_PASSWORD}" && -z "${SSH_PUBKEY}" && -z "${GH_SSH_PUBKEY}" ]]; then + echo -e "${ERROR} Please set 'SSH_PASSWORD' environment variable." + exit 3 +fi + +if [[ -n "$(uname | grep -i Linux)" ]]; then + echo -e "${INFO} Install ngrok ..." + curl -fsSL https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip -o ngrok.zip + unzip ngrok.zip ngrok + rm ngrok.zip + chmod +x ngrok + sudo mv ngrok /usr/local/bin + ngrok -v +elif [[ -n "$(uname | grep -i Darwin)" ]]; then + echo -e "${INFO} Install ngrok ..." + curl -fsSL https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-darwin-amd64.zip -o ngrok.zip + unzip ngrok.zip ngrok + rm ngrok.zip + chmod +x ngrok + sudo mv ngrok /usr/local/bin + ngrok -v + USER=root + echo -e "${INFO} Set SSH service ..." + echo 'PermitRootLogin yes' | sudo tee -a /etc/ssh/sshd_config >/dev/null + sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist + sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist +else + echo -e "${ERROR} This system is not supported!" + exit 1 +fi + +if [[ -n "${SSH_PASSWORD}" ]]; then + echo -e "${INFO} Set user(${USER}) password ..." + echo -e "${SSH_PASSWORD}\n${SSH_PASSWORD}" | sudo passwd "${USER}" +fi + +echo -e "${INFO} Start ngrok proxy for SSH port..." +screen -dmS ngrok \ + ngrok tcp 22 \ + --log "${LOG_FILE}" \ + --authtoken "${NGROK_TOKEN}" \ + --region "${NGROK_REGION:-us}" + +while ((${SECONDS_LEFT:=10} > 0)); do + echo -e "${INFO} Please wait ${SECONDS_LEFT}s ..." + sleep 1 + SECONDS_LEFT=$((${SECONDS_LEFT} - 1)) +done + +ERRORS_LOG=$(grep "command failed" ${LOG_FILE}) + +if [[ -e "${LOG_FILE}" && -z "${ERRORS_LOG}" ]]; then + SSH_CMD="$(grep -oE "tcp://(.+)" ${LOG_FILE} | sed "s/tcp:\/\//ssh ${USER}@/" | sed "s/:/ -p /")" + MSG=" +*GitHub Actions - ngrok session info:* + +⚡ *CLI:* +\`${SSH_CMD}\` + +🔔 *TIPS:* +Run '\`touch ${CONTINUE_FILE}\`' to continue to the next step. +" + if [[ -n "${TELEGRAM_BOT_TOKEN}" && -n "${TELEGRAM_CHAT_ID}" ]]; then + echo -e "${INFO} Sending message to Telegram..." + curl -sSX POST "${TELEGRAM_API_URL:-https://api.telegram.org}/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ + -d "disable_web_page_preview=true" \ + -d "parse_mode=Markdown" \ + -d "chat_id=${TELEGRAM_CHAT_ID}" \ + -d "text=${MSG}" >${TELEGRAM_LOG} + TELEGRAM_STATUS=$(cat ${TELEGRAM_LOG} | jq -r .ok) + if [[ ${TELEGRAM_STATUS} != true ]]; then + echo -e "${ERROR} Telegram message sending failed: $(cat ${TELEGRAM_LOG})" + else + echo -e "${INFO} Telegram message sent successfully!" + fi + fi + while ((${PRT_COUNT:=1} <= ${PRT_TOTAL:=10})); do + SECONDS_LEFT=${PRT_INTERVAL_SEC:=10} + while ((${PRT_COUNT} > 1)) && ((${SECONDS_LEFT} > 0)); do + echo -e "${INFO} (${PRT_COUNT}/${PRT_TOTAL}) Please wait ${SECONDS_LEFT}s ..." + sleep 1 + SECONDS_LEFT=$((${SECONDS_LEFT} - 1)) + done + echo "------------------------------------------------------------------------" + echo "To connect to this session copy and paste the following into a terminal:" + echo -e "${Green_font_prefix}$SSH_CMD${Font_color_suffix}" + echo -e "TIPS: Run 'touch ${CONTINUE_FILE}' to continue to the next step." + echo "------------------------------------------------------------------------" + PRT_COUNT=$((${PRT_COUNT} + 1)) + done +else + echo "${ERRORS_LOG}" + exit 4 +fi + +while [[ -n $(ps aux | grep ngrok) ]]; do + sleep 1 + if [[ -e ${CONTINUE_FILE} ]]; then + echo -e "${INFO} Continue to the next step." + exit 0 + fi +done + +# ref: https://gist.github.com/retyui/7115bb6acf151351a143ec8f96a7c561 diff --git a/tmate2actions.sh b/tmate2actions.sh new file mode 100755 index 0000000..0b4cd14 --- /dev/null +++ b/tmate2actions.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2020 P3TERX +# +# This is free software, licensed under the MIT License. +# See /LICENSE for more information. +# +# https://github.com/P3TERX/ssh2actions +# File name:tmate2actions.sh +# Description: Connect to Github Actions VM via SSH by using tmate +# Version: 2.0 +# + +set -e +Green_font_prefix="\033[32m" +Red_font_prefix="\033[31m" +Green_background_prefix="\033[42;37m" +Red_background_prefix="\033[41;37m" +Font_color_suffix="\033[0m" +INFO="[${Green_font_prefix}INFO${Font_color_suffix}]" +ERROR="[${Red_font_prefix}ERROR${Font_color_suffix}]" +TMATE_SOCK="/tmp/tmate.sock" +TELEGRAM_LOG="/tmp/telegram.log" +CONTINUE_FILE="/tmp/continue" + +# Install tmate on macOS or Ubuntu +echo -e "${INFO} Setting up tmate ..." +if [[ -n "$(uname | grep Linux)" ]]; then + curl -fsSL git.io/tmate.sh | bash +elif [[ -x "$(command -v brew)" ]]; then + brew install tmate +else + echo -e "${ERROR} This system is not supported!" + exit 1 +fi + +# Generate ssh key if needed +[[ -e ~/.ssh/id_rsa ]] || ssh-keygen -t rsa -f ~/.ssh/id_rsa -q -N "" + +# Run deamonized tmate +echo -e "${INFO} Running tmate..." +tmate -S ${TMATE_SOCK} new-session -d +tmate -S ${TMATE_SOCK} wait tmate-ready + +# Print connection info +TMATE_SSH=$(tmate -S ${TMATE_SOCK} display -p '#{tmate_ssh}') +TMATE_WEB=$(tmate -S ${TMATE_SOCK} display -p '#{tmate_web}') +MSG=" +*GitHub Actions - tmate session info:* + +⚡ *CLI:* +\`${TMATE_SSH}\` + +🔗 *URL:* +${TMATE_WEB} + +🔔 *TIPS:* +Run '\`touch ${CONTINUE_FILE}\`' to continue to the next step. +" + +if [[ -n "${TELEGRAM_BOT_TOKEN}" && -n "${TELEGRAM_CHAT_ID}" ]]; then + echo -e "${INFO} Sending message to Telegram..." + curl -sSX POST "${TELEGRAM_API_URL:-https://api.telegram.org}/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ + -d "disable_web_page_preview=true" \ + -d "parse_mode=Markdown" \ + -d "chat_id=${TELEGRAM_CHAT_ID}" \ + -d "text=${MSG}" >${TELEGRAM_LOG} + TELEGRAM_STATUS=$(cat ${TELEGRAM_LOG} | jq -r .ok) + if [[ ${TELEGRAM_STATUS} != true ]]; then + echo -e "${ERROR} Telegram message sending failed: $(cat ${TELEGRAM_LOG})" + else + echo -e "${INFO} Telegram message sent successfully!" + fi +fi + +while ((${PRT_COUNT:=1} <= ${PRT_TOTAL:=10})); do + SECONDS_LEFT=${PRT_INTERVAL_SEC:=10} + while ((${PRT_COUNT} > 1)) && ((${SECONDS_LEFT} > 0)); do + echo -e "${INFO} (${PRT_COUNT}/${PRT_TOTAL}) Please wait ${SECONDS_LEFT}s ..." + sleep 1 + SECONDS_LEFT=$((${SECONDS_LEFT} - 1)) + done + echo "-----------------------------------------------------------------------------------" + echo "To connect to this session copy and paste the following into a terminal or browser:" + echo -e "CLI: ${Green_font_prefix}${TMATE_SSH}${Font_color_suffix}" + echo -e "URL: ${Green_font_prefix}${TMATE_WEB}${Font_color_suffix}" + echo -e "TIPS: Run 'touch ${CONTINUE_FILE}' to continue to the next step." + echo "-----------------------------------------------------------------------------------" + PRT_COUNT=$((${PRT_COUNT} + 1)) +done + +while [[ -S ${TMATE_SOCK} ]]; do + sleep 1 + if [[ -e ${CONTINUE_FILE} ]]; then + echo -e "${INFO} Continue to the next step." + exit 0 + fi +done + +# ref: https://github.com/csexton/debugger-action/blob/master/script.sh