When executing expect scripts, arguments are visible on ps ax which can be a security vulnerability if they are sensitive.
Trying to automate opening a tab on iTerm2, running ssh admin@host and entering the passphrase when asked Enter passphrase for key '/Users/admin/.ssh/key' (the key is encrypted using that passphrase).
Host host
HostName 1.2.3.4
IdentityFile ~/.ssh/key
I would like to supply the passphrase to bash using read -sp 'Passphrase: ' passphrase and then pipe it to expect (which isn’t perfect at all from an OPSEC perspective but much better than having the passphrase leaked on ps ax).
Perhaps there is a better way?
Bellow is some code that works but leaks the passphrase on ps ax. Commented out is what I wish was possible (piping the passphrase to expect).
#!/bin/bash
function new_tab() {
command=${1//\"/\\\"}
osascript \
-e "tell application \"iTerm2\"" \
-e "tell current window" \
-e "create tab with default profile" \
-e "delay 1" \
-e "tell current session" \
-e "write text \"$command\"" \
-e "end tell" \
-e "end tell" \
-e "end tell" > /dev/null
}
hostnames=(
"hostname-1"
"hostname-2"
)
read -sp 'Passphrase: ' passphrase
for hostname in "${hostnames[@]}"; do
# new_tab "echo $passphrase | expect $(pwd)/expect.exp \"$hostname\""
new_tab "expect $(pwd)/expect.exp \"$hostname\" \"$passphrase\""
done
#!/usr/bin/expect
set hostname [lindex $argv 0]
set passphrase [lindex $argv 1]
spawn ssh admin@$hostname
expect "passphrase"
send "$passphrase\r"
interact
In the bashscript, read the password and then export the variable. In expect, access it from the environment with $env(passphrase)
Yes, expect can read from stdin but there is a caveat: reading from stdin isn’t compatible with interact.
See https://stackoverflow.com/a/57847199/4579271
#!/usr/bin/expect
set passphrase [gets stdin]
#!/usr/bin/expect
set data [gets stdin]
scan $data "%s %s" hostname passphrase
Another approach is to use environment variables (as suggested by Glenn) but there is another caveat: environment variables are only available to the shell in which they are defined and its children.
Environment variables defined in batch.sh would therefore not be available in the iTerm2 tabs created using osascript.
So the only secure option I have is to drop osascript altogether and have all the code (batch.sh and expect.exp) execute in the same shell and use environment variables to pass variables between bash and expect.
#!/bin/bash
hostnames=(
"hostname-1"
"hostname-2"
)
read -sp 'SSH key passphrase: ' passphrase
echo ""
export PASSPHRASE=$passphrase
for hostname in "${hostnames[@]}"; do
export HOSTNAME=$hostname
expect "$(dirname "$0")/expect.exp"
done
#!/usr/bin/expect
set timeout 10
spawn ssh admin@$env(HOSTNAME)
expect {
default {
puts "\nCould not connect to $env(HOSTNAME)"
exit 1
}
"passphrase" {
send "$env(PASSPHRASE)\r"
}
}
expect {
default {
puts "\nWrong passphrase"
exit 1
}
"admin@$env(HOSTNAME)" {
# Add automation commands here, then exit SSH session to close expect script moving on to the next hostname
send "exit\r"
}
}
interact
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With