ansibleを使ってみた(playbook偏)

1週間ぶりにアドウェイズの10入社エンジニアのヒラノです(だ)。

__

※この記事を書いている時点ではbash-4.1.2-15.el6_5.1.x86_64.rpmが最新版で、この更新にはまだ脆弱性CVE-2014-7169)がありますのでbash-4.1.2-15.el6_5.2.x86_64.rpmでやってみてください
うまくいけば下記のようになります。

$ cd /home/hirano/ansible/files/
$ wget http://ftp.riken.jp/Linux/centos/6/updates/x86_64/Packages/bash-4.1.2-15.el6_5.2.x86_64.rpm
$  ansible -i hiranon.hosts all -m copy -a "src=/home/hirano/ansible/files/bash-4.1.2-15.el6_5.2.x86_64.rpm dest=/home/ansible/bash-4.1.2-15.el6_5.2.x86_64.rpm"
$  ansible -i hiranon.hosts all -s -a "rpm -Uvh /home/ansible/bash-4.1.2-15.el6_5.2.x86_64.rpm"
$  ansible -i hiranon.hosts all -s -a "env x='() { :;}; echo vulnerable' bash -c 'echo this is a test'"
xxx.xxx.xxx.xxx | success | rc=0 >>
this is a test



前回に続きましてansibleをやっていきます。

Warning!! Warning!!
bashに致命的な脆弱性(CVE-2014-6721)が発生しました!!


キターー!!コレ!(°∀°)
こういうときこそansible!!!

ということで、前回の内容で対応してみた

$  ansible -i hiranon.hosts all -s -m yum -a "name=bash state=latest"


和訳:
ansibleさん -i(サーバーリストファイル指定オプション)hiranon.hostsに書いてる全てのサーバーに次の作業を行ってください。
作業内容
-s: sudoで行います
-m yum: yum向けの命令します
-a "name=bash state=latest": 引数はname=bashとstate=latest
name=bash: yumbashを対象とします。
name=latest: 新しいのがあれば更新します。
直訳:yumbashに新しいあれば、更新してください。

ネットワーク等でyumが使えないものはrpmで更新しましょう。
$  ansible -i hiranon.hosts target_server -m copy -a "src=/home/hirano/bash-4.1.2-15.el6_5.1.x86_64.rpm dest=/home/ansible/bash-4.1.2-15.el6_5.1.x86_64.rpm"
$  ansible -i hiranon.hosts target_server -s -a "rpm -Uvh /home/ansible/bash-4.1.2-15.el6_5.1.x86_64.rpm"
$  ansible -i hiranon.hosts target_server -s -a "/sbin/ldconfig"


和訳:
ansibleさん -i(サーバーリストファイル指定オプション)hiranon.hostsに書いてるtarget_serverに次の作業を行ってください。
作業内容1
-m copy: ファイルを対象サーバーにコピーします
-a "src=/home/hirano/bash-4.1.2-15.el6_5.1.x86_64.rpm dest=/home/ansible/bash-4.1.2-15.el6_5.1.x86_64.rpm":
 引数はsrc=/home/hirano/bash-4.1.2-15.el6_5.1.x86_64.rpmとdest=/home/ansible/bash-4.1.2-15.el6_5.1.x86_64.rpm
src=/home/hirano/bash-4.1.2-15.el6_5.1.x86_64.rpm:
 ローカルの/home/hirano/bash-4.1.2-15.el6_5.1.x86_64.rpmをコピーします。
 
dest=/home/ansible/bash-4.1.2-15.el6_5.1.x86_64.rpm:
 対象サーバーの/home/ansible/bash-4.1.2-15.el6_5.1.x86_64.rpmへコピーします。
作業内容2
-s: sudoで行います
-aのコマンドを実行します。
-a "rpm -Uvh /home/ansible/bash-4.1.2-15.el6_5.1.x86_64.rpm":
 実行コマンドはrpm -Uvh /home/ansible/bash-4.1.2-15.el6_5.1.x86_64.rpm
作業内容3
-s: sudoで行います
-aのコマンドを実行します。
-a "/sbin/ldconfig": 実行コマンド/sbin/ldconfig
直訳:ローカルのbash-4.1.2-15.el6_5.1.x86_64.rpmをコピーして更新してね。

最後に動作チェック
$ ansible -i hiranon.hosts all -s -a "env x='() { :;}; echo vulnerable' bash -c 'echo this is a test'"


和訳:
ansibleさん -i(サーバーリストファイル指定オプション)hiranon.hostsに書いてる全てのサーバーに次の作業を行ってください。
作業内容
-s: sudoで行います
-aのコマンドを実行します。
-a "env x='() { :;}; echo vulnerable' bash -c 'echo this is a test'":
 実行コマンドenv x='() { :;}; echo vulnerable' bash -c 'echo this is a test'
xxx.xxx.xxx.xxx | success | rc=0 >>
this is a testbash: warning: x: ignoring function definition attempt
bash: error importing function definition for `x'

が出力されればOKぽいです。

Playbookで対応すると

$ vim bash_update.yml
- hosts: all
  tasks:
    - name: update check bash
      sudo: yes
      command: env x='() { :;}; exit 1' bash -c 'echo this is a test'
      register: result
      ignore_errors: True
    - name: yum update bash
      sudo: yes
      yum : name=bash state=latest
      ignore_errors: True
      when: result.rc
    - name: update check bash2
      sudo: yes
      command: env x='() { :;}; exit 1' bash -c 'echo this is a test'
      register: result
      ignore_errors: True
    - name: copy rpm
      copy: src=/home/hirano.yuki/ansible/files/bash-4.1.2-15.el6_5.1.x86_64.rpm dest=/home/{{ ansible_ssh_user }}/bash-4.1.2-15.el6_5.1.x86_64.rpm
      when: result.rc
    - name: update bash by rpm
      sudo: yes
      command: rpm -Uvh /home/{{ ansible_ssh_user }}/bash-4.1.2-15.el6_5.1.x86_64.rpm
      when: result.rc
    - name: update lib
      sudo: yes
      command: /sbin/ldconfig
      when: result.rc
    - name: update check bash3
      sudo: yes
      command: env x='() { :;}; exit 1' bash -c 'echo this is a test'
      ignore_errors: True
      when: result.rc
和訳: - hosts: all ホスト全てに実行します。
tasks: 下記のタスクを行います。
- name: update check bash 略
sudo: yes sudoでやるよ
command: env x='() { :;}; exit 1' bash -c 'echo this is a test' 動いてたら、1を返すよ
register: result 結果をresultに格納するよ
ignore_errors: True 失敗しても次のタスクを行うよ
直訳:更新できたか脆弱性のチェックします
- name: yum update bash 「yum update bash」って名前のタスクです。
sudo: yes sudoでやるよ
yum : name=bash state=latest 最新のbashに更新
ignore_errors: True 失敗しても次のタスクを行うよ
直訳:yum最新のbashにしますよ
- name: update check bash2 略
sudo: yes sudoでやるよ
command: env x='() { :;}; exit 1' bash -c 'echo this is a test' 動いてたら、1を返すよ
register: result 結果をresultに格納するよ
ignore_errors: True 失敗しても次のタスクを行うよ
直訳:更新できたか脆弱性のチェックします
- name: copy rpm 略
copy: src=/home/hirano/ansible/files/bash-4.1.2-15.el6_5.1.x86_64.rpm dest=/home/{{ ansible_ssh_user }}/bash-4.1.2-15.el6_5.1.x86_64.rpm
copy: コピーするよ
src=/home/hirano/ansible/files/bash-4.1.2-15.el6_5.1.x86_64.rpm
ローカルの/home/hirano/ansible/files/bash-4.1.2-15.el6_5.1.x86_64.rpm
dest=/home/{{ ansible_ssh_user }}/bash-4.1.2-15.el6_5.1.x86_64.rpm
対象サーバーの/home/{{ ansible_ssh_user }}/bash-4.1.2-15.el6_5.1.x86_64.rpm
({{ ansible_ssh_user }}ログインユーザー名)
when: result|failed 「update check bash3」が失敗していればこのタスクを行うよ
直訳:rpmパッケージをコピーするよ
- name: update bash by rpm 略
sudo: yes sudoでやるよ
command: rpm -Uvh /home/{{ ansible_ssh_user }}/bash-4.1.2-15.el6_5.1.x86_64.rpm
rpm -Uvh /home/{{ ansible_ssh_user }}/bash-4.1.2-15.el6_5.1.x86_64.rpmを実行するよ
when: result|failed 「update check bash3」が失敗していればこのタスクを行うよ
直訳:rpmパッケージで更新するよ
- name: update lib 略
sudo: yes sudoでやるよ
command: /sbin/ldconfig /sbin/ldconfigを実行するよ
直訳:依存チェックするよ
when: result|failed 「update check bash3」が失敗していればこのタスクを行うよ
- name: update check bash3 略
sudo: yes sudoでやるよ
command: env x='() { :;}; exit 1' bash -c 'echo this is a test' 動いてたら、1を返すよ
ignore_errors: True 失敗しても次のタスクを行うよ
when: result|failed 「update check bash3」が失敗していればこのタスクを行うよ
直訳:もう一回脆弱性のチェックを行うよ
$ ansible-playbook -i hiranon.hosts bash_update.yml
PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [server1]
ok: [server2]

TASK: [update check bash] *****************************************************
failed: [server1] => {"changed": true, "cmd": ["env", "x=() { :;}; exit 1", "bash", "-c", "echo this is a test"], "delta": "0:00:00.002746", "end": "2014-09-26 12:56:02.498869", "failed": true, "failed_when_result": true, "rc": 2, "start": "2014-09-26 12:56:02.496123", "stdout_lines": []}
...ignoring

failed: [server2] => {"changed": true, "cmd": ["env", "x=() { :;}; exit 1", "bash", "-c", "echo this is a test"], "delta": "0:00:00.002746", "end": "2014-09-26 12:56:02.498869", "failed": true, "failed_when_result": true, "rc": 2, "start": "2014-09-26 12:56:02.496123", "stdout_lines": []}
...ignoring


TASK: [yum update bash] *******************************************************
changed: [server1]
failed: [server2] => {"changed": false, "failed": true, "rc": 1, "results": ["Loaded plugins: fastestmirror, refresh-packagekit, security\nLoading mirror speeds from cached hostfile\n * base: ftp.tsukuba.wide.ad.jp\n * epel: ftp.kddilabs.jp\n * extras: ftp.tsukuba.wide.ad.jp\n * updates: ftp.tsukuba.wide.ad.jp\nSetting up Update Process\nResolving Dependencies\n--> Running transaction check\n---> Package bash.x86_64 0:4.1.2-15.el6_4 will be updated\n---> Package bash.x86_64 0:4.1.2-15.el6_5.1 will be an update\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package       Arch            Version                   Repository        Size\n================================================================================\nUpdating:\n bash          x86_64          4.1.2-15.el6_5.1          updates          905 k\n\nTransaction Summary\n================================================================================\nUpgrade       1 Package(s)\n\nTotal download size: 905 k\nDownloading Packages:\n"]}
msg: http://ftp.tsukuba.wide.ad.jp/Linux/centos/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: [Errno 14] PYCURL ERROR 7 - "Failed to connect to 2001:200:0:7c06::9393: Network is unreachable"
Trying other mirror.
http://www.ftp.ne.jp/Linux/packages/CentOS/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: [Errno 14] PYCURL ERROR 7 - "Failed to connect to 2001:200:601:10:206:5bff:fef0:466c: Network is unreachable"
Trying other mirror.
http://ftp.riken.jp/Linux/centos/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: [Errno 12] Timeout on http://ftp.riken.jp/Linux/centos/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: (28, 'connect() timed out!')
Trying other mirror.
http://ftp.nara.wide.ad.jp/pub/Linux/centos/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: [Errno 14] PYCURL ERROR 7 - "Failed to connect to 2001:200:0:1::800:21: Network is unreachable"
Trying other mirror.
http://mirrors.aliyun.com/centos/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: [Errno 12] Timeout on http://mirrors.aliyun.com/centos/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: (28, 'connect() timed out!')
Trying other mirror.
http://centos.mirror.secureax.com/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: [Errno 12] Timeout on http://centos.mirror.secureax.com/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: (28, 'connect() timed out!')
Trying other mirror.
http://mirror.vodien.com/centos/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: [Errno 12] Timeout on http://mirror.vodien.com/centos/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: (28, 'connect() timed out!')
Trying other mirror.
http://mirror.nus.edu.sg/centos/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: [Errno 12] Timeout on http://mirror.nus.edu.sg/centos/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: (28, 'connect() timed out!')
Trying other mirror.
http://mirror.neu.edu.cn/centos/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: [Errno 14] PYCURL ERROR 7 - "Failed to connect to 2001:da8:9000::64: Network is unreachable"
Trying other mirror.
http://mirror.bit.edu.cn/centos/6.5/updates/x86_64/Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm: [Errno 14] PYCURL ERROR 7 - "Failed to connect to 2001:da8:204:2001:250:56ff:fea1:22: Network is unreachable"
Trying other mirror.


Error Downloading Packages:
  bash-4.1.2-15.el6_5.1.x86_64: failure: Packages/bash-4.1.2-15.el6_5.1.x86_64.rpm from updates: [Errno 256] No more mirrors to try.


...ignoring

TASK: [update check bash2] ****************************************************
changed: [server1]
changed: [server2]

TASK: [copy rpm] **************************************************************
skipping: [server1]
changed: [server2]

TASK: [update bash by rpm] ****************************************************
skipping: [server1]
changed: [server2]

TASK: [update lib] ************************************************************
skipping: [server1]
changed: [server2]

TASK: [update check bash3] ****************************************************
skipping: [server1]
changed: [server2]

PLAY RECAP ********************************************************************
server1            : ok=3    changed=3    unreachable=0    failed=1
server2            : ok=3    changed=5    unreachable=0    failed=2
和訳:ansible-playbook playbookを使用します。
-i hiranon.hosts 対象サーバーリストを指定します。
bash_update.yml playbookファイルを指定 こんな感じにできて、コレを複数のサーバーで実行できるんだ。ネ、簡単でしょ?
うまく更新できていないと、update check bash3で失敗します。