手元で検証環境の構築なんかをするときは、何らかの形で自動化したくなる。
そんなとき、よく障壁となるのが SSH/SCP でパスワードの入力を求められるところだった。
例えば、複数のホストをまたいで操作したいときや、ソフトウェアが要件として公開鍵の設置を求めてくるときに必要となる。
そういった場面で SSH/SCP でログインするためのパスワード入力を自動化するところが、なかなか面倒くさい。
今回は、そんな折に sshpass
の存在を知って使ってみたところ便利だった、という話。
操作の題材としてはローカルホストに SSH でログインすることを考えてみよう。 尚、あくまでこれはセキュアな環境で検証用の構築などを自動化するために使うことを想定している。 使い方を誤ればセキュリティ上のリスクとなるので注意してほしい。
使った環境は次の通り。
$ cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core) $ uname -r 3.10.0-514.21.1.el7.x86_64
SSH/SCP のログインを自動化する上での問題点
まず、当たり前だけど SSH デーモンでパスワードログインを有効にしている場合には、こんな感じでプロンプトが出る。
$ ssh localhost
vagrant@localhost's password:
あるいは、フィンガープリントが known_hosts
ファイルに載っていない状態では、次のように確認される。
$ ssh localhost The authenticity of host 'localhost (::1)' can't be established. ECDSA key fingerprint is 2a:dd:72:1a:f5:01:be:03:cc:d2:3c:33:11:3b:77:f0. Are you sure you want to continue connecting (yes/no)?
上記のような状況で、ログインを自動化するにはどうしたら良いか?というのが今回のポイント。
ひとまず、フィンガープリントの検証については -o
オプションを使ってスキップできる。
$ ssh -o "StrictHostKeyChecking no" localhost Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts. vagrant@localhost's password:
しかし肝心のログインパスワードの入力はというと…標準入力なんかで入れば楽ちんなんだけど、そうは上手くいかない。
$ echo "vagrant" | ssh -o "StrictHostKeyChecking no" localhost Pseudo-terminal will not be allocated because stdin is not a terminal. vagrant@localhost's password:
ターミナル上での対話の自動化といえば古典的には expect
がよく使われるけど、これもまた面倒くさい。
やりたいことに対してオーバースペック感がある。
sshpass を使ったログインパスワード入力の自動化
そんなとき使うと便利なのが sshpass
だった。
CentOS7 なら EPEL にパッケージがあるのでインストールする。
$ sudo yum -y install epel-release $ sudo yum -y install sshpass
あとは sshpass コマンドに -p
オプションでパスワードを指定しつつ ssh コマンドを実行するだけ。
$ sshpass -p "vagrant" ssh -o "StrictHostKeyChecking no" localhost Last login: Sat Jun 3 03:05:17 2017 from 10.0.2.2 [vagrant@localhost ~]$
あっさりログインできた。
もちろん SCP だってこの通り。
$ echo 'Hello, World!' > greeting.txt $ sshpass -p "vagrant" scp -o "StrictHostKeyChecking no" greeting.txt localhost:/tmp $ cat /tmp/greeting.txt Hello, World!
ばっちりだね。
ssh-copy-id のパスワード入力も自動化できる
ちなみに sshpass
は公開鍵の設置の自動化にも役に立つ。
公開鍵を設置には ssh-copy-id
を使うのが定石なんだけど、これのパスワード入力も代わりにやってくれる。
これも試してみることにしよう。
まずは公開鍵ペアを用意する。
ここでのポイントは -P
オプションでパスフレーズを指定したり -f
オプションで鍵の場所を指定すること。
こうすればインタラクティブモードにならないからワンライナーで作れる。
$ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
あとは、この作った公開鍵をどうやって設置するか、というのが問題になる。
ssh-copy-id
を使えばパーミッションがどうとかいうのを考えずに公開鍵が設置できるのでめっちゃ楽できる。
とはいえ設置するのには SSH でのログインが必要なのでパスワードを聞かれる。
$ ssh-copy-id -i ~/.ssh/id_rsa.pub -o "StrictHostKeyChecking no" localhost /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys vagrant@localhost's password:
なんと、ここの部分も sshpass
で自動化できる!やったー!
さっきと同じように sshpass コマンド経由で ssh-copy-id コマンドを呼び出すだけ。
$ sshpass -p "vagrant" ssh-copy-id -i ~/.ssh/id_rsa.pub -o "StrictHostKeyChecking no" localhost /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys Number of key(s) added: 1 Now try logging into the machine, with: "ssh -o 'StrictHostKeyChecking no' 'localhost'" and check to make sure that only the key(s) you wanted were added.
これでもういくらでも SSH/SCP でのログインが自動化できるね。
$ ssh localhost Last login: Sat Jun 3 03:15:14 2017 from ::1 [vagrant@localhost ~]$
実際に Vagrant で自動化してみる
次は実際に Vagrant を使ったユースケースを試してみることにする。
まずは Shell Provisioner で provision.sh
を実行するようにした Vagrantfile
を用意する。
ポイントは privileged: false
を指定しているところ。
こうすることで、プロビジョニングの実行ユーザが root
ではなく一般ユーザの vagrant
になる。
これをやらないとファイルの権限とかパスの指定を後から付け替えることになって色々とめんどくさいことになる。
$ cat << 'EOF' > Vagrantfile # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.box = "bento/centos-7.3" config.vm.provision "shell", privileged: false do |shell| shell.path = "provision.sh" end end EOF
ちなみに、パスワードログインを SSHD の設定ファイルで無効にしてある Vagrant Box もたまにあるので注意しよう。
続いて上記の Vagrantfile
で実行する provision.sh
を用意する。
この中では localhost
に ssh-copy-id
で公開鍵を設置するところまで自動化している。
$ cat << 'EOF' > provision.sh #!/bin/sh set -x set -e : "Install sshpass(1)" && { sudo yum -y install epel-release sudo yum -y install sshpass } : "Generate SSH keypair" && { ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa } : "Install public key" && { sshpass -p "vagrant" ssh-copy-id -i ~/.ssh/id_rsa.pub -o "StrictHostKeyChecking no" localhost } EOF
上記の設定ファイルを元にして仮想マシンを立ち上げよう。
$ vagrant up Bringing machine 'default' up with 'virtualbox' provider... ==> default: Importing base box 'bento/centos-7.3'... ==> default: Matching MAC address for NAT networking... ...(snip)... ==> default: ==> default: Number of key(s) added: 1 ==> default: ==> default: Now try logging into the machine, with: "ssh -o 'StrictHostKeyChecking no' 'vagrant@localhost'" ==> default: and check to make sure that only the key(s) you wanted were added.
仮想マシンが完成したらログインする。
$ vagrant ssh
すると、この状態で既に localhost
にパスフレーズなしでログインできるようになっている!
$ ssh localhost Last login: Sat Jun 3 04:10:29 2017 from 10.0.2.2 [vagrant@localhost ~]$
めでたしめでたし。
まとめ
- sshpass を使うと SSH/SCP のログインパスワードの入力を自動化できる
- ssh-copy-id と組み合わせて使うことで公開鍵の設置も自動化できる
- 注意点としては、あくまでセキュアな環境で検証用にのみ使うこと
スマートPythonプログラミング: Pythonのより良い書き方を学ぶ
- 作者: もみじあめ
- 発売日: 2016/03/12
- メディア: Kindle版
- この商品を含むブログ (1件) を見る