capistrano3 ssh経由でリモートサーバのパッケージをyumアップデートする

はじめに
===

capistrano3サーバのcapistranoタスクを実行して、sshでリモートサーバへ接続して、yumでパッケージをアップデートする例について記載致します。

いささか古い事例ではありますが、bash ShellShock等のセキュリティ脆弱性対応として、各サーバのbashパッケージをyumでアップデートしたいといった事があるかと思います。

今回の例では、capistrano3サーバに対して、リモートサーバのbashをアップデートするcapistrano taskを作成し、ssh経由でリモートサーバ(CentOS 6.5)のbashをアップデートする例について記載致します。

免責事項
===
本内容に書かれているスクリプトや設定等を使用して発生した問題につきまして、当方は一切責任を負いません。恐れ入りますが、スクリプトや設定等をご利用される場合は自己責任でお願い致します。

capistrano3サーバの環境
===

capistranoは以下の手順により、AWS EC2インスタンスに構築したcapistrano3 + Ruby 2.2.0サーバを利用致します。環境は以下に準じます。

http://qiita.com/na0AaooQ/items/74d8e7a9a2c72cfd1483

bashアップデート対象の例示用サーバについて
===

今回の例では、bashアップデート対象として、OSインストール直後のCentOS 6.5サーバ(例示用IPアドレス 198.51.100.11)のbashバージョンを以下にアップデートします。

　bash-4.1.2-15.el6_5.2.x86_64　→　bash-4.1.2-29.el6.x86_64

capistrano3サーバからbashアップデート対象のリモートサーバ(198.51.100.11)に対しては、「ssh example@198.51.100.11」コマンドでssh接続可能な前提で記載させて頂きます。

capistrano3サーバ側の設定 (capistranoタスクの作成)
===

capistrano3サーバに対して、リモートサーバのbashをyum updateによりアップデートするcapistranoタスクを作成します。

今回の例では、以下のcapistranoタスクを作成します。

・リモートサーバのbashバージョンを表示します。

```
bundle exec cap develop bash_update_utils:show_bash_version
```

・リモートサーバの/bin/bashファイルをcpコマンドでバックアップします。

```
bundle exec cap develop bash_update_utils:backup_bash
```

・リモートサーバのbashをyum -y update bashコマンドでアップデートします。

```
bundle exec cap develop bash_update_utils:update_bash
```


まずcapistrano3サーバにログインし、capistranoタスクを定義したutils.rakeファイルをバックアップします。

```
[capistrano@example-capistrano-server capistrano]$ cp -p /home/capistrano/capistrano/lib/capistrano/tasks/utils.rake /home/capistrano/capistrano/lib/capistrano/tasks/utils.rake.`date '+%Y%m%d_%H%M%S'`
[capistrano@example-capistrano-server capistrano]$

[capistrano@example-capistrano-server capistrano]$ diff /home/capistrano/capistrano/lib/capistrano/tasks/utils.rake /home/capistrano/capistrano/lib/capistrano/tasks/utils.rake.`date '+%Y%m%d_%H%M%S'`
[capistrano@example-capistrano-server capistrano]$
```

以下のようにbashパッケージをアップデートするcapistranoタスクを作成します。

```
[capistrano@example-capistrano-server capistrano]$ vi /home/capistrano/capistrano/lib/capistrano/tasks/utils.rake
```

```rb:utils.rake
namespace :bash_update_utils do
  task :show_bash_version do
    on roles(:web) do
      execute "rpm -qa | grep bash"
      execute "bash --version"
      execute "ls -lrta /bin/bash"
    end
  end
  task :backup_bash do
    on roles(:web) do
      execute "sudo -u root cp -p /bin/bash /bin/bash.`date '+%Y%m%d_%H%M%S'`"
    end
  end
  task :update_bash do
    on roles(:web) do
      execute "sudo -u root yum -y update bash"
    end
  end
end
```

以下の内容が記載されている事を確認します。

```
[capistrano@example-capistrano-server ~]$ cat /home/capistrano/capistrano/lib/capistrano/tasks/utils.rake
namespace :bash_update_utils do
  task :show_bash_version do
    on roles(:web) do
      execute "rpm -qa | grep bash"
      execute "bash --version"
      execute "ls -lrta /bin/bash"
    end
  end
  task :backup_bash do
    on roles(:web) do
      execute "sudo -u root cp -p /bin/bash /bin/bash.`date '+%Y%m%d_%H%M%S'`"
    end
  end
  task :update_bash do
    on roles(:web) do
      execute "sudo -u root yum -y update bash"
    end
  end
end
[capistrano@example-capistrano-server ~]$
```

capistrano3サーバ側の設定 (bashアップデート対象のリモートサーバのIPアドレス記述)
===

bashアップデート対象のサーバ名やIPアドレスを記述致します。

```
[capistrano@example-capistrano-server ~]$ cp -p /home/capistrano/capistrano/config/deploy/develop.rb /home/capistrano/capistrano/config/deploy/develop.rb.`date '+%Y%m%d_%H%M%S'`
[capistrano@example-capistrano-server ~]$
```

以下のように記述致します。

```
[capistrano@example-capistrano-server ~]$ vi /home/capistrano/capistrano/config/deploy/develop.rb
```

```rb:develop.rb
role :web, %w{capistrano@198.51.100.11}
```

```
[capistrano@example-capistrano-server capistrano]$ cat /home/capistrano/capistrano/config/deploy/develop.rb
role :web, %w{capistrano@198.51.100.10}
[capistrano@example-capistrano-server capistrano]$
```

なお、bashアップデート対象サーバが複数ある場合は、develop.rbに対して、半角スペースを区切りとして、以下のように複数サーバのIPアドレスを記述します。

```rb:develop.rb
role :web, %w{example@198.51.100.10 example@198.51.100.11}
```


bashアップデート対象のサーバの状態(bashアップデート前)
===

bashアップデート対象のリモートサーバ(198.51.100.11)のbashアップデート実行前のバージョンを確認します。
例として、bashアップデート前の状態が以下であるとします。

```
[root@not-aws-vpc-server-198-51-100-11 ~]# rpm -qa | grep bash
bash-4.1.2-15.el6_5.2.x86_64
[root@not-aws-vpc-server-198-51-100-11 ~]# bash --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
[root@not-aws-vpc-server-198-51-100-11 ~]#
```

```
[root@not-aws-vpc-server-198-51-100-11 ~]# ll /bin/bash*
-rwxr-xr-x. 1 root root 903848 Sep 26 02:13 /bin/bash
[root@not-aws-vpc-server-198-51-100-11 ~]#
```


capistrano3サーバからリモートサーバのbashバージョンを表示する
===

以下のcapistranoタスクを実行し、リモートサーバのbashバージョンを表示します。

```
bundle exec cap develop bash_update_utils:show_bash_version
```

以下の例のようにリモートサーバのbashバージョンが表示されます。

```
[capistrano@example-capistrano-server ~]$ hostname
example-capistrano-server
[capistrano@example-capistrano-server ~]$ cd /home/capistrano/capistrano/
[capistrano@example-capistrano-server capistrano]$ pwd
/home/capistrano/capistrano
[capistrano@example-capistrano-server capistrano]$ id
uid=XXXXX(capistrano) gid=XXXXX(capistrano) groups=XXXXX(capistrano)
[capistrano@example-capistrano-server capistrano]$
```

```
[capistrano@example-capistrano-server capistrano]$ bundle exec cap develop bash_update_utils:show_bash_version
INFO [e10c1ae1] Running /usr/bin/env rpm -qa | grep bash as example@198.51.100.11
DEBUG [e10c1ae1] Command: rpm -qa | grep bash
DEBUG [e10c1ae1]        bash-4.1.2-15.el6_5.2.x86_64
INFO [e10c1ae1] Finished in 0.497 seconds with exit status 0 (successful).
INFO [d71f0746] Running /usr/bin/env bash --version as example@198.51.100.11
DEBUG [d71f0746] Command: bash --version
DEBUG [d71f0746]        GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
DEBUG [d71f0746]        Copyright (C) 2009 Free Software Foundation, Inc.
DEBUG [d71f0746]        License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
DEBUG [d71f0746]
DEBUG [d71f0746]        This is free software; you are free to change and redistribute it.
DEBUG [d71f0746]        There is NO WARRANTY, to the extent permitted by law.
INFO [d71f0746] Finished in 0.023 seconds with exit status 0 (successful).
INFO [f18f5605] Running /usr/bin/env ls -lrta /bin/bash as example@198.51.100.11
DEBUG [f18f5605] Command: ls -lrta /bin/bash
DEBUG [f18f5605]        -rwxr-xr-x. 1 root root 903848 Sep 26 11:13 /bin/bash
INFO [f18f5605] Finished in 0.023 seconds with exit status 0 (successful).
[capistrano@example-capistrano-server capistrano]$
```

capistrano3サーバからリモートサーバの/bin/bashファイルをバックアップする
===

以下のcapistranoタスクを実行し、リモートサーバの/bin/bashファイルをcpコマンドでバックアップします。

```
bundle exec cap develop bash_update_utils:backup_bash
```

以下の例のようにリモートサーバの/bin/bashがバックアップされます。

```
[capistrano@example-capistrano-server capistrano]$ pwd
/home/capistrano/capistrano
[capistrano@example-capistrano-server capistrano]$ bundle exec cap develop bash_update_utils:backup_bash
INFO [bfe157be] Running /usr/bin/env sudo -u root cp -p /bin/bash /bin/bash.`date '+%Y%m%d_%H%M%S'` as example@198.51.100.11
DEBUG [bfe157be] Command: sudo -u root cp -p /bin/bash /bin/bash.`date '+%Y%m%d_%H%M%S'`
INFO [bfe157be] Finished in 0.338 seconds with exit status 0 (successful).
[capistrano@example-capistrano-server capistrano]$
```

bashバージョンアップ対象のサーバでは、以下のように/bin/bashのバックアップファイルが作成されます。

```
[root@not-aws-vpc-server-198-51-100-11 ~]# ll /bin/bash*
-rwxr-xr-x. 1 root root 903848 Sep 26 02:13 /bin/bash
-rwxr-xr-x. 1 root root 903848 Sep 26 02:13 /bin/bash.20150128_120003
[root@not-aws-vpc-server-198-51-100-11 ~]#

[root@not-aws-vpc-server-198-51-100-11 ~]# diff /bin/bash /bin/bash.20150128_120003
[root@not-aws-vpc-server-198-51-100-11 ~]#
```


capistrano3サーバからリモートサーバのbashをアップデートする
===

以下のcapistranoタスクを実行し、リモートサーバのbashをyum -y update bashコマンドでアップデートします。

```
bundle exec cap develop bash_update_utils:backup_bash
```

以下の例のようにリモートサーバのbashがアップデートされます。

```
[capistrano@example-capistrano-server capistrano]$ pwd
/home/capistrano/capistrano
[capistrano@example-capistrano-server capistrano]$ bundle exec cap develop bash_update_utils:update_bash
INFO [1871977d] Running /usr/bin/env sudo -u root yum -y update bash as example@198.51.100.11
DEBUG [1871977d] Command: sudo -u root yum -y update bash
DEBUG [1871977d]        Loaded plugins: fastestmirror, presto
DEBUG [1871977d]        Loading mirror speeds from cached hostfile
DEBUG [1871977d]         * base: ftp.nara.wide.ad.jp
DEBUG [1871977d]         * extras: ftp.nara.wide.ad.jp
DEBUG [1871977d]         * updates: ftp.nara.wide.ad.jp
DEBUG [1871977d]        Setting up Update Process
DEBUG [1871977d]        Resolving Dependencies
DEBUG [1871977d]        --> Running transaction check
DEBUG [1871977d]        ---> Package bash.x86_64 0:4.1.2-15.el6_5.2 will be updated
DEBUG [1871977d]        ---> Package bash.x86_64 0:4.1.2-29.el6 will be an update
DEBUG [1871977d]        --> Finished Dependency Resolution
DEBUG [1871977d]
DEBUG [1871977d]        Dependencies Resolved
DEBUG [1871977d]
DEBUG [1871977d]        ================================================================================
DEBUG [1871977d]         Package        Arch             Version                   Repository      Size
DEBUG [1871977d]        ================================================================================
DEBUG [1871977d]        Updating:
DEBUG [1871977d]         bash           x86_64           4.1.2-29.el6              base           907 k
DEBUG [1871977d]
DEBUG [1871977d]        Transaction Summary
DEBUG [1871977d]        ================================================================================
DEBUG [1871977d]        Upgrade       1 Package(s)
DEBUG [1871977d]
DEBUG [1871977d]        Total download size: 907 k
DEBUG [1871977d]        Downloading Packages:
DEBUG [1871977d]        Setting up and reading Presto delta metadata
DEBUG [1871977d]        Processing delta metadata
DEBUG [1871977d]        Package(s) data still to download: 907 k
bash-4.1.2-29.el6.x86_64.rpm                             | 907 kB     00:00
DEBUG [1871977d]        warning: rpmts_HdrFromFdno: Header V3 RSA/SHA1 Signature, key ID c105b9de: NOKEY
DEBUG [1871977d]        Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
DEBUG [1871977d]        Importing GPG key 0xC105B9DE:
DEBUG [1871977d]         Userid : CentOS-6 Key (CentOS 6 Official Signing Key) <centos-6-key@centos.org>
DEBUG [1871977d]         Package: centos-release-6-5.el6.centos.11.2.x86_64 (@CentOS6-Updates/6.5)
DEBUG [1871977d]         From   : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
DEBUG [1871977d]        Running rpm_check_debug
DEBUG [1871977d]        Running Transaction Test
DEBUG [1871977d]        Transaction Test Succeeded
DEBUG [1871977d]        Running Transaction
  Updating   : bash-4.1.2-29.el6.x86_64 [                                 ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [#                                ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [##                               ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [###                              ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [####                             ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [#####                            ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [######                           ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [#######                          ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [########                         ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [#########                        ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [##########                       ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [###########                      ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [############                     ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [#############                    ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [##############                   ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [###############                  ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [################                 ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [#################                ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [##################               ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [###################              ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [####################             ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [#####################            ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [######################           ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [#######################          ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [########################         ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [#########################        ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [##########################       ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [###########################      ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [############################     ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [#############################    ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [##############################   ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [###############################  ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64 [################################ ] 1/2
  Updating   : bash-4.1.2-29.el6.x86_64                                     1/2
  Cleanup    : bash-4.1.2-15.el6_5.2.x86_64                                 2/2
  Verifying  : bash-4.1.2-29.el6.x86_64                                     1/2
  Verifying  : bash-4.1.2-15.el6_5.2.x86_64                                 2/2
DEBUG [1871977d]
DEBUG [1871977d]        Updated:
DEBUG [1871977d]          bash.x86_64 0:4.1.2-29.el6
DEBUG [1871977d]
DEBUG [1871977d]        Complete!
INFO [1871977d] Finished in 3.526 seconds with exit status 0 (successful).
[capistrano@example-capistrano-server capistrano]$
```

capistrano3サーバからリモートサーバのbashのバージョンがアップデートされたか確認する
===

以下のcapistranoタスクを実行し、リモートサーバのbashバージョンがアップデートされたか確認します。

```
bundle exec cap develop bash_update_utils:show_bash_version
```

rpm -qaコマンドでbashのバージョンがアップデートされている事を確認します。
　bash-4.1.2-15.el6_5.2.x86_64　→　bash-4.1.2-29.el6.x86_64

ls -lrta /bin/bashコマンドの結果で、bashコマンドが更新されている事も確認します。

```
[capistrano@example-capistrano-server capistrano]$ bundle exec cap develop bash_update_utils:show_bash_version
INFO [8399abd3] Running /usr/bin/env rpm -qa | grep bash as example@198.51.100.11
DEBUG [8399abd3] Command: rpm -qa | grep bash
DEBUG [8399abd3]        bash-4.1.2-29.el6.x86_64
INFO [8399abd3] Finished in 0.582 seconds with exit status 0 (successful).
INFO [65f1aa0d] Running /usr/bin/env bash --version as example@198.51.100.11
DEBUG [65f1aa0d] Command: bash --version
DEBUG [65f1aa0d]        GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
DEBUG [65f1aa0d]        Copyright (C) 2009 Free Software Foundation, Inc.
DEBUG [65f1aa0d]        License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
DEBUG [65f1aa0d]
DEBUG [65f1aa0d]        This is free software; you are free to change and redistribute it.
DEBUG [65f1aa0d]        There is NO WARRANTY, to the extent permitted by law.
INFO [65f1aa0d] Finished in 0.023 seconds with exit status 0 (successful).
INFO [daa1634b] Running /usr/bin/env ls -lrta /bin/bash as example@198.51.100.11
DEBUG [daa1634b] Command: ls -lrta /bin/bash
DEBUG [daa1634b]        -rwxr-xr-x. 1 root root 904872 Oct 16 22:56 /bin/bash
INFO [daa1634b] Finished in 0.022 seconds with exit status 0 (successful).
[capistrano@example-capistrano-server capistrano]$
```

bashアップデート対象のサーバの状態(bashアップデート後の確認)
===

念の為、bashアップデート対象サーバのbashアップデート状態を手動で確認したい場合、以下のように確認すると良いと思います。

以下の例では、bashアップデート対象のリモートサーバ(198.51.100.11)のbashアップデート後の状態を確認しています。

rpm -qaコマンドでbashのバージョンがアップデートされている事を確認します。
　bash-4.1.2-15.el6_5.2.x86_64　→　bash-4.1.2-29.el6.x86_64

```
[root@not-aws-vpc-server-198-51-100-11 ~]# rpm -qa | grep bash
bash-4.1.2-29.el6.x86_64
[root@not-aws-vpc-server-198-51-100-11 ~]#
```

ll /bin/bash*コマンドの結果で、bashのバイナリファイルが更新されている事、/bin/bashファイルのバックアップが作成されている事も確認します。

```
[root@not-aws-vpc-server-198-51-100-11 ~]# su - root
[root@not-aws-vpc-server-198-51-100-11 ~]#
[root@not-aws-vpc-server-198-51-100-11 ~]# bash --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
[root@not-aws-vpc-server-198-51-100-11 ~]#

[root@not-aws-vpc-server-198-51-100-11 ~]# ll /bin/bash*
-rwxr-xr-x. 1 root root 904872 Oct 16 22:56 /bin/bash
-rwxr-xr-x. 1 root root 903848 Sep 26 11:13 /bin/bash.20150128_210312
[root@not-aws-vpc-server-198-51-100-11 ~]#
```

一応、bashアップデート後にbashが動作する事も確認しておきます。

```
[root@not-aws-vpc-server-198-51-100-11 ~]# su - example

[example@not-aws-vpc-server-198-51-100-11 ~]$ echo $SHELL
/bin/bash
[example@not-aws-vpc-server-198-51-100-11 ~]$ id
uid=XXX(example) gid=XXX(example) groups=XXX(example) XXXXXXXXXX
[example@not-aws-vpc-server-198-51-100-11 ~]$
```

```
cat << _EOT_ > /home/example/example_bash_test.sh
#!/bin/bash

echo "bash test"

_EOT_
```

```
[example@not-aws-vpc-server-198-51-100-11 ~]$ cat << _EOT_ > /home/example/example_bash_test.sh
> #!/bin/bash
>
> echo "bash test"
>
> _EOT_
[example@not-aws-vpc-server-198-51-100-11 ~]$ chmod 755 /home/example/example_bash_test.sh
[example@not-aws-vpc-server-198-51-100-11 ~]$
```

```
[example@not-aws-vpc-server-198-51-100-11 ~]$ /home/example/example_bash_test.sh
bash test
[example@not-aws-vpc-server-198-51-100-11 ~]$
```

bashをアップデートした場合、ShellShock対応済みである事も確認した方が良いと思います。

```
[example@not-aws-vpc-server-198-51-100-11 ~]$ rpm -qa | grep bash
bash-4.1.2-29.el6.x86_64
[example@not-aws-vpc-server-198-51-100-11 ~]$ ll /bin/bash*
-rwxr-xr-x. 1 root root 904872 Oct 16 22:56 /bin/bash
-rwxr-xr-x. 1 root root 903848 Sep 26 11:13 /bin/bash.20150128_210312
[example@not-aws-vpc-server-198-51-100-11 ~]$ echo $SHELL
/bin/bash
[example@not-aws-vpc-server-198-51-100-11 ~]$
```

```
[example@not-aws-vpc-server-198-51-100-11 ~]$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
this is a test
[example@not-aws-vpc-server-198-51-100-11 ~]$
```

以上になります。