メリークリスマス! なのまる です。
NTPの脆弱性(英語)の対応しよーと思って、手作業はツラすぎるのである程度の自動化をしようと思いました。
もくじ
Fabricが楽しかった理由
そもそもCapistrano (Ruby) を使っていたんですがなんとなく、一度だけ勉強会で使わせてもらったFabricの勉強をしてみたいと思って使いました!Fabricを使ってみて、楽しいなぁ~って思った理由を自分なりにまとめてみたので書いておきます。
- Capistranoでは、そのままでは煩わしい部分が簡単に解決できた!(認証関連)
- 出来上がった、コードが短くて済んだ!
- 出来上がった、コードがわかりやすい!
- 上記もあって、使っていて楽しい!w
Fabric を使ってみる!
前提条件
- OSシステム環境のPythonに影響を及ぼさない
- pyenv + virtualenv
- Linux (CentOS 6)
- fabric
そのため「pyenv + virtualenv」で実装した。
「pyenv + virtualenv」 インストール・設定
ここの部分長いので、わかる人は飛ばしていいと思います!pyenv インストール
pyenvはinstallerがあって、インストールが簡単です!以下を実行するだけ!
curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash
インストール状況
[snickerjp@localhost ~]$ curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 101 2126 101 2126 0 0 6321 0 --:--:-- --:--:-- --:--:-- 6858 Initialized empty Git repository in /home/snickerjp/.pyenv/.git/ remote: Counting objects: 8056, done. remote: Total 8056 (delta 0), reused 0 (delta 0) Receiving objects: 100% (8056/8056), 1.44 MiB | 374 KiB/s, done. Resolving deltas: 100% (5898/5898), done. Initialized empty Git repository in /home/snickerjp/.pyenv/plugins/pyenv-doctor/.git/ remote: Counting objects: 26, done. ~中略~ Resolving deltas: 100% (8/8), done. WARNING: seems you still have not added 'pyenv' to the load path. # Load pyenv automatically by adding # the following to ~/.bash_profile: export PATH="$HOME/.pyenv/bin:$PATH" eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)"
~/.bash_profileに以下を追記
export PATH="$HOME/.pyenv/bin:$PATH" eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)"
かっこよく編集してみたりw
cat << 'EOF' >> ~/.bash_profile # for pyenv export PATH="$HOME/.pyenv/bin:$PATH" eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)" EOF
localにPythonのインストール
なんとなく2.x系をインストールしました。# Pythonの現在のバージョンを確認 [snickerjp@localhost ~]$ python --version Python 2.6.6 [snickerjp@localhost ~]$ pyenv install 2.7.8 Downloading Python-2.7.8.tgz... ~略~ Installed Python-2.7.8 to /home/snickerjp/.pyenv/versions/2.7.8 [snickerjp@localhost ~]$ pyenv versions * system (set by /home/snickerjp/.pyenv/version) 2.7.8 [snickerjp@localhost ~]$ pyenv install 2.7.9 Downloading Python-2.7.9.tgz... ~略~ [snickerjp@localhost ~]$ pyenv versions * system (set by /home/snickerjp/.pyenv/version) 2.7.8 2.7.9
Pythonのインストールでエラーが出たので、追加でdevelパッケージを入れました。
WARNING: The Python readline extension was not compiled. Missing the GNU readline lib? WARNING: The Python bz2 extension was not compiled. Missing the bzip2 lib? WARNING: The Python sqlite3 extension was not compiled. Missing the SQLite3 lib? ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?
yumでインストール!
sudo yum install readline-devel bzip2-devel openssl-devel sqlite-devel
virtualenvのインストール
virtualenvのインストール~[snickerjp@localhost fabric-bin]$ pyenv virtualenv 2.7.9 fabric Collecting virtualenv Downloading virtualenv-12.0.3-py2.py3-none-any.whl (1.8MB) 100% |################################| 1.8MB 6.2MB/s Installing collected packages: virtualenv Successfully installed virtualenv-12.0.3 New python executable in /home/snickerjp/.pyenv/versions/fabric/bin/python2.7 Also creating executable in /home/snickerjp/.pyenv/versions/fabric/bin/python Installing setuptools, pip...done. Ignoring indexes: https://pypi.python.org/simple/ Requirement already satisfied (use --upgrade to upgrade): setuptools in /home/snickerjp/.pyenv/versions/fabric/lib/python2.7/site-packages Requirement already satisfied (use --upgrade to upgrade): pip in /home/snickerjp/.pyenv/versions/fabric/lib/python2.7/site-packages Cleaning up... [snickerjp@localhost fabric-bin]$ [snickerjp@localhost fabric-bin]$ pyenv versions * system (set by /home/snickerjp/.pyenv/version) 2.7.8 2.7.9 fabric
localのPythonを使う場所を作る
localバージョンのPythonを使う場所を作ります![snickerjp@localhost ~]$ mkdir fabric-bin [snickerjp@localhost fabric-bin]$ cd fabric-bin/ [snickerjp@localhost fabric-bin]$ pyenv local fabric pyenv-virtualenv: activate fabric (fabric)[snickerjp@localhost fabric-bin]$ (fabric)[snickerjp@localhost fabric-bin]$ pyenv rehash (fabric)[snickerjp@localhost fabric-bin]$ python --version Python 2.7.9 (fabric)[snickerjp@localhost fabric-bin]$ pip list pip (6.0.3) setuptools (8.2.1)参考
fabric インストール
やっと、ここでfabricのインストール!もうvirtualenvでlocal環境にインストールできる状態です!
(fabric)[snickerjp@localhost fabric-bin]$ pip install fabric Collecting fabric Downloading Fabric-1.10.1.tar.gz (209kB) 100% |################################| 212kB 9.3MB/s Collecting paramiko>=1.10 (from fabric) Downloading paramiko-1.15.2-py2.py3-none-any.whl (165kB) 100% |################################| 167kB 10.8MB/s Collecting ecdsa>=0.11 (from paramiko>=1.10->fabric) Downloading ecdsa-0.11.tar.gz (45kB) 100% |################################| 49kB 10.3MB/s Collecting pycrypto!=2.4,>=2.1 (from paramiko>=1.10->fabric) Downloading pycrypto-2.6.1.tar.gz (446kB) 100% |################################| 446kB 8.1MB/s Installing collected packages: pycrypto, ecdsa, paramiko, fabric Running setup.py install for pycrypto checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.out ~略~ gcc -pthread -shared -L/home/snickerjp/.pyenv/versions/2.7.9/lib build/temp.linux-x86_64-2.7/src/_counter.o -o build/lib.linux-x86_64-2. 7/Crypto/Util/_counter.so Running setup.py install for ecdsa Running setup.py install for fabric Installing fab script to /home/snickerjp/.pyenv/versions/fabric/bin Successfully installed ecdsa-0.11 fabric-1.10.1 paramiko-1.15.2 pycrypto-2.6.1
参考
ntp をアップデートしてみる
いよいよ本題ですね!wntpup.py
こちらを参考に以下のコードを書いてみました!
(コメント部分は消してください)
#coding:utf-8 from fabric.api import env, run, sudo from fabric.contrib.console import confirm env.use_ssh_config = True env.key_filename = ['~/.ssh/id_rsa'] def yum_update_ntp(): sudo('cat /etc/∗-release',user='root', pty=True) # Linuxのディストリビューションの確認 sudo('yum -q -y update ntp',user='root', pty=True) # sudo で yum update def run_su(command, user="root"): # sudo が無いサーバーなどの対応 return run('su %s -c "%s"' % (user, command), pty=True) def su_update_ntp(): run_su('cat /etc/∗-release',user='root') run_su('yum -y update ntp',user='root') # sudo がないサーバーで yum update
実行例
[192.168.82.xxx] Executing task 'yum_update_ntp' [192.168.82.xxx] sudo: cat /etc/*-release [192.168.82.xxx] Login password for 'snickerjp': [192.168.82.xxx] out: [192.168.82.xxx] out: We trust you have received the usual lecture from the local System [192.168.82.xxx] out: Administrator. It usually boils down to these three things: [192.168.82.xxx] out: [192.168.82.xxx] out: #1) Respect the privacy of others. [192.168.82.xxx] out: #2) Think before you type. [192.168.82.xxx] out: #3) With great power comes great responsibility. [192.168.82.xxx] out: [192.168.82.xxx] out: sudo password: [192.168.82.xxx] out: Sorry, try again. [192.168.82.xxx] out: sudo password: ← 公開鍵とPAMで違うパスワードの時は聞いてきてくれる! [192.168.82.xxx] out: NAME="Amazon Linux AMI" [192.168.82.xxx] out: VERSION="2014.09" [192.168.82.xxx] out: ID="amzn" [192.168.82.xxx] out: ID_LIKE="rhel fedora" [192.168.82.xxx] out: VERSION_ID="2014.09" [192.168.82.xxx] out: PRETTY_NAME="Amazon Linux AMI 2014.09" [192.168.82.xxx] out: ANSI_COLOR="0;33" [192.168.82.xxx] out: CPE_NAME="cpe:/o:amazon:linux:2014.09:ga" [192.168.82.xxx] out: HOME_URL="http://aws.amazon.com/amazon-linux-ami/" [192.168.82.xxx] out: Amazon Linux AMI release 2014.09 [192.168.82.xxx] out: [192.168.82.xxx] sudo: yum --releasever=2014.09 --disablerepo=epel update ntp [192.168.82.xxx] out: sudo password: [192.168.82.xxx] out: Loaded plugins: priorities, update-motd, upgrade-helper [192.168.82.xxx] out: [192.168.82.xxx] out: amzn-main/2014.09 | 2.1 kB 00:00 [192.168.82.xxx] out: [192.168.82.xxx] out: amzn-updates/2014.09 | 2.3 kB 00:00 [192.168.82.xxx] out: 181 packages excluded due to repository priority protections [192.168.82.xxx] out: No packages marked for update [192.168.82.xxx] out:SSH関連について
Capistranoでやろうとすると、このあたりが比較的にめんどくさい!
- 公開鍵とPAMで違うパスワードでも対話で入力できる!
- rootパスワードも対話で入力できる!
- サーバーごとにパスワード違っても対話で入力できる!
- 前の処理で入れたパスワードは記憶しておいてくれる!
fabricだと、楽だった!のでした!
参考
まとめ
- Capistranoで不便と思っていた部分が解決できる!(認証関連)
- コードが短くて、さらに読みやすい!
- pyenv + virtualenv + fabric でポータビリティもあるんじゃないかと!w
参考サイト
- Welcome to Fabric! — Fabric documentation
- virtualenv 12.0.4 : Python Package Index
- NTPに複数の脆弱性 - US-CERTが注意喚起 | マイナビニュース
- 時刻同期のNTPに極めて深刻な脆弱性--「パケット1つで悪用が可能」 - ZDNet Japan
- Network Time Protocol Vulnerabilities (Update A) | ICS-CERT
- (capistrano) A remote server automation and deployment tool written in Ruby.