
メリークリスマス! なのまる です。
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.