タイトル詰め込みすぎ。
SSH公開鍵を登録するときにしばしばauthorized_keys
を設定します。
最近知ったのですが結構色々オプションが指定できます。詳しくはドキュメントをお読みください。
今回は特定の公開鍵でログインしたときに実行するコマンドを指定するオプションを紹介します。
例えば、サーバの再起動だけ行えるようにしておいて、ある運用者にその秘密鍵を共有することで、再起動以外の余計な操作をできないようにすることができ、気持ちセキュアに運用を組めます。
例
たとえばログインしたらlsを実行して終了するようにしてみます。
ただ、lsだけではかわいそうなので、引数を指定できるようにします。
あらかじめ秘密鍵と公開鍵を用意しておき、リモートのauthorized_keysに公開鍵を以下のように書きます。
command="ls $SSH_ORIGINAL_COMMAND" ssh-rsa AAAAB3...
SSH_ORIGINAL_COMMANDはsshコマンドの引数の情報が入った環境変数です。
試してみましょう。
あくまでsshコマンドなので、--
を入れないと、-l
がsshのオプションとして処理されてしまいます。
ssh USER@HOST -- -l /tmp
ここまでは簡単ですね。
(ちなみに、sshd_config
のForceCommand
が設定されていればそちらが優先されます。)
引数の扱いが難しい問題
引数を処理してましたが、上記のとおり、$@
ではなく、環境変数 SSH_ORIGINAL_COMMAND
を使う必要があります。これは普通の環境変数なので文字列です。
なので、空白の扱いに困ることになります。
例えば以下の場合、引数は2つとして処理してほしいものですが、うまくいきません。
$ ssh USER@HOST a "b c"
ls: cannot access a: No such file or directory
ls: cannot access b: No such file or directory
ls: cannot access c: No such file or directory
というわけで、今回はこれをどうにかします。(本題)
authorized_keysは以下のようにします。ログイン時のシェルがbashならこんな感じにかけます。
command="read -a ssh_args <<< \"$SSH_ORIGINAL_COMMAND\" && ls \"${ssh_args[@]}\"" ssh-rsa AAAAB3...
使うときはこうします。
$ ssh USER@HOST "$(printf "%q " a "b c")"
ls: cannot access a: No such file or directory
ls: cannot access b c: No such file or directory
printf "%q "
でいい感じにエスケープがかかるので、それをリモート側のbashのread -a aname
入力として使い、いい感じに処理できます。
おまけ:醜さ軽減
authorized_keys
がエスケープだらけで醜い場合はスクリプト化するとよいでしょう。
command="/path/to/script.sh" ssh-rsa AAAAB3...
# !/bin/bash
read -a ssh_args <<< "$SSH_ORIGINAL_COMMAND"
ls "${ssh_args[@]}"
また、実行側のsshコマンドもつらいですね。
ホスト決め打ち、sshのオプションとSSH_ORIGINAL_COMMANDを厳密に区別しなくて良いのであれば、functionなりシェルスクリプトなりにしておくと良いでしょう。
function ssh_1(){
ssh USER@HOST -- "$(printf "%q " "$@")"
}
$ ssh_1 a "b c"
ls: cannot access a: No such file or directory
ls: cannot access b c: No such file or directory