Last active
April 20, 2022 02:45
-
-
Save Shoozza/8fe8b0c85fa89cd3b1c4 to your computer and use it in GitHub Desktop.
Make Cmder work with ssh-agent
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@ECHO OFF | |
SETLOCAL | |
GOTO:MAIN | |
REM | |
REM Info functions start | |
REM | |
REM Display version and copyright information | |
:VERSION | |
ECHO,Agent 1.0.0.0 (ssh-agent script for MSYS2) | |
ECHO, | |
ECHO,Copyright (C^) 2014-2021 Gregor A. Cieslak. | |
ECHO, | |
ECHO,License GPLv3+: GNU GPL version 3 or later ^<https://gnu.org/licenses/gpl.html^>. | |
ECHO,This is free software: you are free to change and redistribute it. | |
ECHO,There is NO WARRANTY, to the extent permitted by law. | |
GOTO:EOF | |
REM Display usage information | |
:USAGE | |
ECHO,Adds missing ssh-keys to an instance of ssh-agent. | |
ECHO,Starts a new instance if ssh-agent is not running or sock file is invalid. | |
ECHO,Use with MSYS2 command line tools (https://www.msys2.org/^). | |
ECHO, | |
ECHO,Requirements: | |
ECHO, %%HOME%%\.ssh folder with ssh keys in any of the following formats: | |
ECHO, rsa, dsa, ecdsa, ecdsa_sk, ed25519, ed25519_sk | |
ECHO, MSYS2 installation with following command line tools: | |
ECHO, cygpath, rm, sed, awk, grep, ps, ssh-add, ssh-keygen, ssh-agent | |
ECHO, | |
ECHO,Usage: agent [OPTION] | |
ECHO, | |
ECHO,OPTION: | |
ECHO, -c, --check check requirements | |
ECHO, -h, --help display this help text | |
ECHO, -k, --kill kill all ssh-agent processes | |
ECHO, -v, --verbose verbose mode | |
ECHO, -V --version display version | |
GOTO:EOF | |
REM | |
REM Info functions end | |
REM | |
REM | |
REM Entry point start | |
REM | |
:MAIN | |
REM Parse command line arguments | |
IF NOT "%~2" == "" GOTO:USAGE | |
IF "%~1" == "-h" GOTO:USAGE | |
IF "%~1" == "--help" GOTO:USAGE | |
IF "%~1" == "-k" GOTO:KILLSSHAGENT | |
IF "%~1" == "--kill" GOTO:KILLSSHAGENT | |
IF "%~1" == "-c" GOTO:CHECKREQUIREMENTS | |
IF "%~1" == "--check" GOTO:CHECKREQUIREMENTS | |
IF "%~1" == "-V" GOTO:VERSION | |
IF "%~1" == "--version" GOTO:VERSION | |
REM Check for verbose output | |
SET "VERBOSE=" | |
IF "%~1" == "-v" ( | |
SET "VERBOSE=true" | |
) ELSE IF "%~1" == "--verbose" ( | |
SET "VERBOSE=true" | |
) ELSE IF NOT "%~1" == "" GOTO:USAGE | |
CALL:LOG "[INFO] Adding missing ssh keys:" | |
CALL:LOG "-------------------------------------------" | |
REM Set default sock file if missing | |
SET "DEFAULT_AUTH_SOCK=/tmp/ssh-agent.sock" | |
IF "%SSH_AUTH_SOCK%" == "" GOTO:SETDEFAULTSOCK | |
IF "%SSH_AUTH_SOCK%" == "%DEFAULT_AUTH_SOCK%" GOTO:SETDEFAULTSOCK | |
CALL:LOG "[INFO] Checking preexisting ssh-agent sock file" | |
GOTO:CHECKSOCKFILE | |
:SETDEFAULTSOCK | |
SET "SSH_AUTH_SOCK=%DEFAULT_AUTH_SOCK%" | |
CALL:LOG "[INFO] Checking default ssh-agent sock file" | |
:CHECKSOCKFILE | |
REM Check if path to socket file is available | |
FOR /f "tokens=*" %%I IN ('cygpath -w "%SSH_AUTH_SOCK%"') DO SET "VAR=%%I" | |
IF "%SSH_AUTH_SOCK%" == "%DEFAULT_AUTH_SOCK%" ( | |
IF NOT EXIST "%VAR%" GOTO:RUNAGENT | |
) ELSE ( | |
IF NOT EXIST "%VAR%" GOTO:SETDEFAULTSOCK | |
) | |
CALL:LOG "[INFO] Found ssh-agent sock file" | |
REM Check if an ssh-agent is running | |
FOR /f "tokens=*" %%I IN ('ps ^| grep ssh-agent ^| sed "s/^ *\([0-9]\+\) .*/\1/"') DO SET "VAR=%%I" | |
IF "%SSH_AUTH_SOCK%" == "%DEFAULT_AUTH_SOCK%" ( | |
IF "%VAR%" == "" GOTO:RUNAGENT | |
) ELSE ( | |
IF "%VAR%" == "" GOTO:CHECKDEFAULTSOCK | |
) | |
CALL:LOG "[INFO] Found ssh-agent process" | |
REM Check if socket file is valid | |
ssh-add -l 1> NUL 2>&1 | |
IF ERRORLEVEL 1 ( | |
CALL:LOG "[INFO] Failed to validate sock file" | |
IF "%SSH_AUTH_SOCK%" == "%DEFAULT_AUTH_SOCK%" ( | |
GOTO:RUNAGENT | |
) ELSE ( | |
GOTO:SETDEFAULTSOCK | |
) | |
) | |
CALL:LOG "[INFO] Found valid sock file" | |
GOTO:ADDKEYS | |
:RUNAGENT | |
CALL:LOG "[INFO] Starting new ssh-agent" | |
REM Don't delete %%SSH_AUTH_SOCK%% - could be set to a dangerous path | |
IF NOT "%SSH_AUTH_SOCK%" == "%DEFAULT_AUTH_SOCK%" GOTO:SKIPDELETESOCK | |
REM Remove old default socket file if available | |
FOR /f "tokens=*" %%I IN ('cygpath -w "%DEFAULT_AUTH_SOCK%"') DO SET "VAR=%%I" | |
IF EXIST "%VAR%" rm -f -- "%DEFAULT_AUTH_SOCK%" | |
SET "SSH_AUTH_SOCK=%DEFAULT_AUTH_SOCK%" | |
:SKIPDELETESOCK | |
REM Run ssh-agent and save (last) PID in VAR | |
SET "VAR=" | |
FOR /f "tokens=*" %%J IN ('ssh-agent -a "%SSH_AUTH_SOCK%"') DO FOR /f "tokens=*" %%K IN ('ECHO,%%J ^| grep "SSH_AGENT_PID" ^| sed "s/^SSH_AGENT_PID=\([0-9]\+\); .*/\1/"') DO SET "VAR=%%K" | |
:ADDKEYS | |
SET "SSH_AGENT_PID=%VAR%" | |
REM Check if ssh keys are known | |
SET "KEYS=" | |
SET /A "KEYCOUNT=0" | |
FOR /f "tokens=*" %%I IN ('DIR /B "%HOME%\.ssh\*_rsa" "%HOME%\.ssh\*_dsa" "%HOME%\.ssh\*_ecdsa" "%HOME%\.ssh\*_ecdsa_sk" "%HOME%\.ssh\*_ed25519" "%HOME%\.ssh\*_ed25519_sk" 2^> NUL') DO CALL:CHECKKEY %%I | |
REM Print ssh key count | |
IF %KEYCOUNT% == 1 ( | |
CALL:LOG "[INFO] Found %KEYCOUNT% ssh key" | |
) ELSE ( | |
CALL:LOG "[INFO] Found %KEYCOUNT% ssh keys" | |
) | |
REM Add all missing ssh keys | |
IF NOT "%KEYS%" == "" ( | |
CALL:LOG "[INFO] Adding ssh keys" | |
ssh-add %KEYS% | |
) ELSE ( | |
CALL:LOG "[INFO] All ssh keys already added" | |
) | |
CALL:LOG "===========================================" | |
CALL:LOG "[INFO] Done" | |
ENDLOCAL & SET "SSH_AGENT_PID=%SSH_AGENT_PID%" & SET "SSH_AUTH_SOCK=%SSH_AUTH_SOCK%" | |
GOTO:EOF | |
REM | |
REM Entry point end | |
REM | |
REM | |
REM Functions start | |
REM | |
REM Check if ssh key has to be added | |
:CHECKKEY | |
SET /A "KEYCOUNT=KEYCOUNT+1" | |
SET "FINGERPRINT=" | |
FOR /f "tokens=*" %%J IN ('ssh-keygen -lf "%HOME%\.ssh\%1" 2^>nul ^| awk "{print $2}"') DO SET "FINGERPRINT=%%J" | |
IF "%FINGERPRINT%" == "" GOTO:EOF | |
SET "VAR=" | |
FOR /f "tokens=*" %%J IN ('ssh-add -l 2^>nul ^| awk "{print $2}" ^| grep "%FINGERPRINT%"') DO SET "VAR=%%J" | |
IF "%VAR%" == "" SET "KEYS='%HOME%\.ssh\%1' %KEYS%" | |
GOTO:EOF | |
REM Output text in verbose mode | |
:LOG | |
IF "%VERBOSE%" == "" GOTO:EOF | |
ECHO,%~1 | |
GOTO:EOF | |
REM Check if required command line tools, folders and ssh keys are available | |
:CHECKREQUIREMENTS | |
SET "FAILED=" | |
ECHO,[INFO] Checking requirements... | |
ECHO,------------------------------------------- | |
CALL:CHECKPROGEXISTS cygpath | |
IF NOT "%FAILED%"=="" GOTO:SKIPTMPPATHCHECK | |
FOR /f "tokens=*" %%I IN ('cygpath -w /tmp') DO SET "TMPPATH=%%I" | |
IF EXIST "%TMPPATH%" ( | |
ECHO,[OK] found /tmp folder | |
) ELSE ( | |
ECHO,[FAIL] missing /tmp folder | |
SET "FAILED=true" | |
) | |
:SKIPTMPPATHCHECK | |
IF EXIST "%HOME%\.ssh\" ( | |
ECHO,[OK] found %%HOME%%\.ssh folder | |
) ELSE ( | |
ECHO,[FAIL] missing %%HOME%%\.ssh folder | |
SET "FAILED=true" | |
) | |
CALL:CHECKPROGEXISTS rm | |
CALL:CHECKPROGEXISTS sed | |
CALL:CHECKPROGEXISTS awk | |
CALL:CHECKPROGEXISTS grep | |
CALL:CHECKPROGEXISTS ps | |
CALL:CHECKPROGEXISTS ssh-add | |
CALL:CHECKPROGEXISTS ssh-keygen | |
CALL:CHECKPROGEXISTS ssh-agent | |
SET "KEYS=" | |
SET /A "KEYCOUNT=0" | |
FOR /f "tokens=*" %%I IN ('DIR /B "%HOME%\.ssh\*_rsa" "%HOME%\.ssh\*_dsa" "%HOME%\.ssh\*_ecdsa" "%HOME%\.ssh\*_ecdsa_sk" "%HOME%\.ssh\*_ed25519" "%HOME%\.ssh\*_ed25519_sk" 2^> NUL') DO CALL:CHECKKEY %%I | |
IF NOT %KEYCOUNT% == 0 ( | |
IF %KEYCOUNT% == 1 ( | |
ECHO,[OK] found %KEYCOUNT% ssh key | |
) ELSE ( | |
ECHO,[OK] found %KEYCOUNT% ssh keys | |
) | |
) ELSE ( | |
ECHO,[FAIL] missing ssh keys | |
SET "FAILED=true" | |
) | |
ECHO,=========================================== | |
IF "%FAILED%"=="" ( | |
ECHO,[OK] Success! All requirements are met | |
) ELSE ( | |
ECHO,[FAIL] Failure! Some requirements are not met! | |
) | |
GOTO:EOF | |
REM Check if programm is in path | |
:CHECKPROGEXISTS | |
WHERE /q %1 | |
IF ERRORLEVEL 1 ( | |
ECHO,[FAIL] missing %1 in PATH | |
SET "FAILED=true" | |
) ELSE ( | |
ECHO,[OK] found %1 | |
) | |
GOTO:EOF | |
REM Kills all ssh-agent processes | |
:KILLSSHAGENT | |
SET /A "KILLCOUNT=0" | |
FOR /f "tokens=*" %%I IN ('ps ^| grep ssh-agent ^| awk "{print $1}"') DO ( | |
IF NOT "%%I" == "" ( | |
KILL %%I | |
SET /A "KILLCOUNT=KILLCOUNT+1" | |
) | |
) | |
ECHO,[INFO] killed %KILLCOUNT% ssh-agent processes | |
GOTO:EOF | |
REM | |
REM Functions end | |
REM |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey everyone since this script is not really necessary for cmder,
I decided to fix and update this script to work with MSYS2 (and possibly cygwin).
Cmder provides a start-ssh-agent script from git-for-windows by default.
Updated and extended the script:
Add license
Add kill command
Add verbose output
Add help/usage info
Add version/license info
Add dependency check support
Add support for adding all kinds of ssh keys
Add comments
Add support for checking already set SSH_AUTH_SOCK before using DEFAULT_AUTH_SOCK
Modify use ECHO, for faster output
Fix don't leak/overwrite environment variables except SSH_AUTH_SOCK and SSH_AGENT_PID if successfull
Fix check for the sock file in the correct folder (/tmp != %TEMP%)
Fix valid sock file check needs to check with fingerprint instead of non working path
Have fun ;)