use ~/.ssh/git-annex-shell wrapper

This was needed for the OSX self-contained app, but is a generally good
idea. It avoids needing perl; is probably faster; and could eventually
be replaced by something faster yet.
This commit is contained in:
Joey Hess 2012-09-26 18:59:18 -04:00
parent 0af20bded4
commit 3979086035
3 changed files with 28 additions and 5 deletions

View file

@ -47,7 +47,8 @@ ensureInstalled = do
let content = unlines let content = unlines
[ "#!/bin/sh" [ "#!/bin/sh"
, "set -e" , "set -e"
, "exec", base </> "runshell" ++ " git-annex-shell \"$@\"" , "exec", base </> "runshell" ++
" git-annex-shell -c \"$SSH_ORIGINAL_COMMAND\""
] ]
curr <- catchDefaultIO "" $ readFile shim curr <- catchDefaultIO "" $ readFile shim
when (curr /= content) $ do when (curr /= content) $ do

View file

@ -119,10 +119,20 @@ removeAuthorizedKeys rsynconly pubkey = do
writeFile keyfile $ unlines $ filter (/= keyline) ls writeFile keyfile $ unlines $ filter (/= keyline) ls
{- Implemented as a shell command, so it can be run on remote servers over {- Implemented as a shell command, so it can be run on remote servers over
- ssh. -} - ssh.
-
- The ~/.ssh/git-annex-shell wrapper script is created if not already
- present.
-}
addAuthorizedKeysCommand :: Bool -> SshPubKey -> String addAuthorizedKeysCommand :: Bool -> SshPubKey -> String
addAuthorizedKeysCommand rsynconly pubkey = join "&&" addAuthorizedKeysCommand rsynconly pubkey = join "&&"
[ "mkdir -p ~/.ssh" [ "mkdir -p ~/.ssh"
, join "; "
[ "if [ ! -e " ++ wrapper ++ " ]"
, "then (" ++ join ";" (map echoval script) ++ ") > " ++ wrapper
, "fi"
]
, "chmod 700 " ++ wrapper
, "touch ~/.ssh/authorized_keys" , "touch ~/.ssh/authorized_keys"
, "chmod 600 ~/.ssh/authorized_keys" , "chmod 600 ~/.ssh/authorized_keys"
, unwords , unwords
@ -131,15 +141,23 @@ addAuthorizedKeysCommand rsynconly pubkey = join "&&"
, ">>~/.ssh/authorized_keys" , ">>~/.ssh/authorized_keys"
] ]
] ]
where
echoval v = "echo " ++ shellEscape v
wrapper = "~/.ssh/git-annex-shell"
script =
[ "#!/bin/sh"
, "set -e"
, "exec git-annex-shell -c \"$SSH_ORIGINAL_COMMAND\""
]
authorizedKeysLine :: Bool -> SshPubKey -> String authorizedKeysLine :: Bool -> SshPubKey -> String
authorizedKeysLine rsynconly pubkey authorizedKeysLine rsynconly pubkey
{- TODO: Locking down rsync is difficult, requiring a rather {- TODO: Locking down rsync is difficult, requiring a rather
- long perl script. -} - long perl script. -}
| rsynconly = pubkey | rsynconly = pubkey
| otherwise = limitcommand "git-annex-shell -c" ++ pubkey | otherwise = limitcommand ++ pubkey
where where
limitcommand c = "command=\"perl -e 'exec qw(" ++ c ++ "), $ENV{SSH_ORIGINAL_COMMAND}'\",no-agent-forwarding,no-port-forwarding,no-X11-forwarding " limitcommand = "command=\"~/.ssh/git-annex-shell\",no-agent-forwarding,no-port-forwarding,no-X11-forwarding "
{- Generates a ssh key pair. -} {- Generates a ssh key pair. -}
genSshKeyPair :: IO SshKeyPair genSshKeyPair :: IO SshKeyPair

View file

@ -175,7 +175,8 @@ parseSshRsyncUrl u
- a special ssh key will need to be generated just for this server. - a special ssh key will need to be generated just for this server.
- -
- Once logged into the server, probe to see if git-annex-shell is - Once logged into the server, probe to see if git-annex-shell is
- available, or rsync. - available, or rsync. Note that on OSX, ~/.ssh/git-annex-shell may be
- present, while git-annex-shell is not in PATH.
-} -}
testServer :: SshInput -> IO (Either ServerStatus SshData) testServer :: SshInput -> IO (Either ServerStatus SshData)
testServer (SshInput { hostname = Nothing }) = return $ testServer (SshInput { hostname = Nothing }) = return $
@ -200,6 +201,7 @@ testServer sshinput@(SshInput { hostname = Just hn }) = do
[ report "loggedin" [ report "loggedin"
, checkcommand "git-annex-shell" , checkcommand "git-annex-shell"
, checkcommand "rsync" , checkcommand "rsync"
, checkcommand osx_shim
] ]
knownhost <- knownHost hn knownhost <- knownHost hn
let sshopts = filter (not . null) $ extraopts ++ let sshopts = filter (not . null) $ extraopts ++
@ -214,6 +216,7 @@ testServer sshinput@(SshInput { hostname = Just hn }) = do
parsetranscript . fst <$> sshTranscript sshopts "" parsetranscript . fst <$> sshTranscript sshopts ""
parsetranscript s parsetranscript s
| reported "git-annex-shell" = UsableSshInput | reported "git-annex-shell" = UsableSshInput
| reported osx_shim = UsableSshInput
| reported "rsync" = UsableRsyncServer | reported "rsync" = UsableRsyncServer
| reported "loggedin" = UnusableServer | reported "loggedin" = UnusableServer
"Neither rsync nor git-annex are installed on the server. Perhaps you should go install them?" "Neither rsync nor git-annex are installed on the server. Perhaps you should go install them?"
@ -224,6 +227,7 @@ testServer sshinput@(SshInput { hostname = Just hn }) = do
checkcommand c = "if which " ++ c ++ "; then " ++ report c ++ "; fi" checkcommand c = "if which " ++ c ++ "; then " ++ report c ++ "; fi"
token r = "git-annex-probe " ++ r token r = "git-annex-probe " ++ r
report r = "echo " ++ token r report r = "echo " ++ token r
osx_shim = "~/.ssh/git-annex-shell"
{- Runs a ssh command; if it fails shows the user the transcript, {- Runs a ssh command; if it fails shows the user the transcript,
- and if it succeeds, runs an action. -} - and if it succeeds, runs an action. -}