特定のssh鍵だけが登録されたssh-agentを簡単に起動する
使いたい鍵だけを登録したssh-agentを用意するPythonコード
run-ssh-agent.py#!/usr/bin/env python
"""
$ python run-ssh-agent.py
"""
import os
import sys
import pickle
import subprocess
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
KEY_AND_PASSPHRSE = {
'SERVER1.key': 'secret-passphrase-for-server1',
}
def register_keys():
# 鍵の登録先となるssh-agentを起動させる
ret = subprocess.run('ssh-agent', stdout=subprocess.PIPE, encoding='ascii')
logger.debug('start agent: %s', ret.stdout)
env = os.environ.copy()
# 起動したssh-agentのSSH_AGENT_PIDを環境変数に登録する
env.update({
k: v.rstrip(';')
for k, v in [part.split('=') for part in ret.stdout.split() if '=' in part]
})
env['SSH_ASKPASS'] = os.path.abspath(sys.argv[0])
env['DISPLAY'] = ':999'
logger.debug('env: %s', env)
for keyfile, phrase in KEY_AND_PASSPHRSE.items():
env['PASSPHRASE'] = phrase
p = subprocess.Popen(
['ssh-add', os.path.abspath(keyfile)],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=env,
encoding='ascii',
preexec_fn=os.setsid
)
try:
r = p.communicate(timeout=1)
logger.debug('ssh-add return %s: %s', p.returncode, r)
except subprocess.TimeoutExpired:
logger.error('timeout')
p.kill()
logger.error(p.communicate())
break
# 登録されている鍵の一覧を表示
p = subprocess.run(
['ssh-add', '-l'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=env,
encoding='ascii',
)
logger.debug('ssh-add -l\n%s', p.stdout)
# 本来はagentは起動しっぱなしにしたいが、今回は実験を繰り返すためagentを終了させておく
ret = subprocess.run(['ssh-agent', '-k'], env=env, stdout=subprocess.PIPE, encoding='ascii')
logger.debug(ret.stdout)
def main():
if os.environ.get('PASSPHRASE'):
# ssh-addから呼ばれる、ssh-askpassとしての動作
print(os.environ['PASSPHRASE'])
sys.exit(0)
else:
register_keys()
if __name__ == '__main__':
main()
この機能を一般化してOSSで公開した