Glide Note

glidenote's blog

ChatOpsでOSのセキュリティアップデートを自動化出来るようにした

先日@naoya_itoさんが自身のブログ(インフラの継続的デリバリー)KAIZEN platform Inc.のインフラについて書いていたやつの続編的な内容。

TL;DR

  • Chat(Slack) + Hubot + CircleCI + GitHub を用いてセキュリティアップデートを自動化した
  • GitHubのPull Requestを契機にセキュリティアップデートを実行できるようにした
  • CircleCIが大変便利。インフラ系の作業を自動化するのに非常に合っている気がする

背景

KAIZEN platform Inc.では、

  1. ネットワーク脆弱性スキャン
  2. アプリケーション脆弱性スキャン
  3. セキュリティアップデートの定期実行

の3つをセキュリティ系タスクとして継続的にやっていこうという話になり、今回は私が担当した、「セキュリティアップデートの定期実行」の話。

RHEL系OSにはyumの自動更新機能がありますが、これが稼働していて意図せずミドルウェアがバージョンアップして、 過去にみんな痛い目に遭遇した経験があるので、これは利用せずにアップデートの内容を事前に確認したいという事情もあります。

仕組みの詳細

全体の流れ

  1. 定期的にHubot自身が、Chat(Slack)上からHubotにSecurity Checkを指示する(今回はキャプチャを取るために私が召喚してます)
  2. Hubot経由でCircleCIのAPIを叩いて、Security Update用リポジトリ上にチェック用ブランチを作成して、GitHubにPush
  3. GitHubへのPushを検知して、CircleCIが検証環境であるQA環境のサーバに対して、sshしてyum --secuity check-updateを実行
  4. セキュリティ更新があれば、下記のようなデプロイ用ブランチへのPull Requestを作ってインフラメンバーにmentionを送る。無ければそのまま終了。
  5. インフラメンバーがPull Request内容を確認して、問題が無ければMerge。
  6. デプロイ用ブランチへのMergeを契機に対象サーバについてyum --security -y updateがかかり、セキュリティアップデートがかかる
  7. アップデート後にCircleCI経由でSlack上のHubotを召還
  8. Hubot経由でe2eテストが自動で走り、セキュリティアップデートによって、アプリケーションに不具合が発生していないかテストされる
  9. e2eテストに問題が無ければ、Production環境のサーバ向けに2-8の手順を繰り返す
  10. 最終的には下記のように、どのサービス、どのステージでセキュリティアップデートが完了したかが通知される
  11. 寿司を食う

この一連の流れが各ロール(web,log,proxy,batch等々)のサーバ数十台に対して一斉に自動で走ってくれて、 進捗報告もChat(Slack)に都度通知されるようになっている。

人の手を介するのは5のセキュリティアップデート内容のレビューとMergeボタンを押す部分だけ。

naoyaさんのブログから画像を拝借すると、セキュリティアップデートの適用もMergeボタンに集約された感じ。

これにより

  • 定期的なセキュリティアップデートのチェックを自動化
  • セキュリティアップデートをPull Requestでレビュー可能に
  • CircleCI経由で実行することで、CircleCI上に作業ログの保存

が出来るようになった。

CircleCIについて

CircleCIには

  • ssh鍵やTOKENがセキュアに渡すことが出来る
  • 実行ログが残せる
  • Chat系アプリと簡単に連携できる
  • UIが直感的で分かりやすい
  • CircleCI自体にssh出来るので、デバッグが簡単に出来る

という特徴があるので、インフラ系の作業を自動化するのには非常に合っていると思う。(某OSSなCIツールで同じ事をやろうとすると、そこまで行くのにいろいろと設定が必要でyak shavingな感じが…)

私が担当した以外のセキュリティ系タスクも自動化がされているし、 Chefの適用、セキュリティスキャンなどChatOpsの範囲が広がってきて、最近はサーバにほとんど入らなくなってきているので もっと頑張れば寿司だけ食っていれば良い世界が来るかもしれない。

Slackのチャンネル移動をキーボードで簡単に出来るようKarabinerのprivate.xmlを書いた

仕事でSlackを使っているんですが、 キーボードショートカットがあんまり使いやすくなくて、 特にチャンネル移動が致命的に使いにくくてストレスフルなので、、Karabiner(旧keyremap2makbook)のprivate.xmlを書いた。 (Slackのメニューにチャンネル移動の項目がないので、Macの環境設定からキーバインドの設定が出来ないのでKarabinerで実現してます)

今までWeechatというIRCクライアントを使っていたので、そのキーバインドに合わせた。 具体的には

  • Ctrl + Nで次のチャンネル or DMに移動
  • Ctrl + Pで前のチャンネル or DMに移動
  • Alt + Aで未読チャンネル or DMに移動

導入方法

~/Library/Application\ Support/Karabiner/private.xml に下記のように設定を追加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0"?>
<root>

    <appdef>
        <appname>SLACK</appname>
        <equal>com.tinyspeck.slackmacgap</equal>
    </appdef>
    <item>
        <name>For Slack CTRL+N=move next channel, CTRL+P=move previous channel, ALT+A=move unread channel</name>
        <identifier>private.app_slack_move_channel_with_ctrln_ctrlp</identifier>
        <only>SLACK</only>
        <autogen>__KeyToKey__ KeyCode::N, ModifierFlag::CONTROL_L, KeyCode::CURSOR_DOWN, ModifierFlag::OPTION_L</autogen>
        <autogen>__KeyToKey__ KeyCode::P, ModifierFlag::CONTROL_L, KeyCode::CURSOR_UP, ModifierFlag::OPTION_L</autogen>
        <autogen>__KeyToKey__ KeyCode::A, ModifierFlag::OPTION_L, KeyCode::CURSOR_DOWN, ModifierFlag::OPTION_L, ModifierFlag::SHIFT_L</autogen>
    </item>

</root>

これでKarabinerの設定画面からReloadXMLをして、設定にチェックを入れれば動くようになる。

これでホームポジションから動かずにSlackがだいたい操作できるようになって快適になった。

KAIZEN platform Inc.に入社した

いわゆる転職エントリーなので、興味無い人はそっと閉じて頂ければ幸いです。

私事ですが、6年弱勤め、シニアエンジニアとしてサービスのインフラ系業務を担当していたGMOペパボ株式会社(旧株式会社paperboy&co.)を7月末に退職して、 8月からKAIZEN platform Inc.に入社しました。

なぜKAIZEN platform Inc.を選んだのか

CEO 須藤憲司さんのブログ、技術顧問である伊藤直也さんのブログや 出演していたRebuildで知っていたのもあるんですが、入社を決めたポイントをまとめると下記のような感じ。

  • 前職でKAIZEN platform Inc.のplanBCDを導入しており、非常に高い効果がありプロダクトに関心があった
  • 創業間も無いのに優秀なエンジニアが揃っており、技術的にもチャレンジングで尖ったことをやっていた
  • 本気で海外進出を目指しており(会議はもちろん全編英語)、エンジニアだけでなく、営業やバックオフィスにも優秀な人材を揃えていた
  • 企業理念が「世界をKAIZEN(改善)する」ということで、世の中を良くしていこうとしている会社だから
  • 面接で企業の成長速度、事業計画や採用計画を聞いていて、今参加しないと1〜2年後には入社が不可能なレベルの会社になっていると感じた

KAIZEN platform Inc.がよく分かるまとめ

KAIZEN platform Inc.のことを知らないひとに向けてちょっとまとめを。

CEO 須藤憲司さんの記事

CTO 石橋利真さんの記事

技術顧問 伊藤直也さんの記事

GMOペパボについて

転職エントリーを書くと、転職元に対して地味にダメージを与える傾向があるので、誤解が無いよう書いておこうと思う。 GMOペパボは、上場企業で福利厚生もちゃんとしているし、エンジニアの評価制度もしっかりしていて、エンジニアにとって働きやすく素晴らしい会社だと思う。 優秀なエンジニアも多数在籍しているし、新しい事にも積極的に取り組んでいて、刺激的な環境で本当にオススメの会社だと思う。

私が辞めたのはいわゆるベンチャー志向であるからであって、ペパボに不満があったとかでは無いです。 ベンチャー志向については2007年の伊藤直也さんの動画を観るとよく分かります。(素晴らしい動画です)

既にペパボを退職されていますが、ペパボではServerspecでお馴染みのmizzyさんという一流エンジニアと一緒に働くことが出来て、 非常に多くの事を吸収することが出来、エンジニアとしても、人生において素晴らしい時間を過ごすことが出来た。

社長のケンタロさんを始め、多くの人々に支えられ、ペパボには感謝しか無いです。

最後に

転職エントリにつきもののウィッシュリストを用意したので、 KAIZEN platform Inc.の新しい住所宛〒163-0241 東京都新宿区西新宿2-6-1 新宿住友ビル41Fに送って頂けると大変助かります!!

Wishlist

今後ともよろしくお願いします。

Roadworkerとdirenvを使ってRoute53のDNSレコードを管理する & Roadworker用にVimプラグインとZsh補完関数も作った

TL;DR

  • Route53のDNSレコード管理にはRoadworkerとdirenvを組み合わせて使うと便利
  • Roadworkerを使いやすくするために、VimプラグインとZsh補完関数を作った

(TL;DR使ってみたかった)

経緯

会社でRoute53に移行したチームがあって、レコードの管理にRoadworkerを使ってて、 私もちょっと使ってみたんですが、コマンドラインからの使い勝手と、Routefileの編集が そのままだと不便だったので、使い勝手が良くなるようにdirenv使ったり、 Vimプラグインとzsh補完関数を作ったりした。

Macでの作業を想定してます。

Roadworkerのインストール

1
gem install roadworker

direnvのインストール

direnvはgoで書かれていてbrewコマンドで導入が可能。

1
brew install direnv

~/.zshrcに下記を追記。(もし$EDITORが設定されてない場合はそれも設定する)

1
eval "$(direnv hook zsh)"

Roadworkerとdirenvを組み合わせて使う

Routeworkerを使うときに下記のように

1
2
export AWS_ACCESS_KEY_ID='...'
export AWS_SECRET_ACCESS_KEY='...'

AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYを環境変数を設定しないといけないんですが、 毎回設定するのが面倒なので、これをdirenvにやって貰う。

具体的には、Route53のドメインを管理する(Routefileを管理している)ディレクトリに移動して、 direnv経由で、.envrcを作成する

1
direnv edit .

.envrcの中身は下記のような感じ

1
2
export AWS_ACCESS_KEY_ID='...'
export AWS_SECRET_ACCESS_KEY='...'

そうすると、コマンドラインから環境変数を設定しなくても、該当ディレクトリに移動すると そのディレクトリ内だけでdirenvが.envrcを読み込んで環境変数が設定される。

あとは普通にroadworkコマンドでRoute53を操作するだけ。Roadworkerの使い方は下記が詳しいです。

roadworker.vim

RoadworkerからRoute53を操作するのに、Routefileの編集が必要なので、 Routefileの編集が楽になるようにプラグインを書いた。

下記みたいにsyntaxがきいたり、snippetを利用して簡単に編集が出来るようになります。 (左がsyntax無し、右がroadworker.vimによりsyntax有りの状態)

導入方法や使い方はREADME.mdを参照ください。

zsh補完関数

コマンドラインからも便利に使えるようにzsh補完関数を下記みたいなファイルを作成。

$fpathの中に設置すれば、下記みたいな感じで動きます。(時間があるときに体裁整えて zsh-users/zsh-completionsにPR出しておきます!)

Roadworkerを利用すれば、DNSレコードをRoutefileという形でgit管理出来るし、変更点をdry-runで事前チェックも出来る。 またテストコマンドもあるのでCI回したりして、より安全にドメイン操作が出来ると思う。(まだそこまで使いこなせてないけど!)

@deeeetさんがブログに書いてたようにDotenvより direnvの方が他のツールと組み合わせやすくて便利な気がする。

参考

peco/percolでCUIなスニペットツールを作ってみる

以前にSheetというスニペットツールを利用すると大変便利と書いた。

で、障害対応で使うコマンドとかよく忘れるコマンドを大量に登録してて、毎日使ってて重宝してるんですが、スニペットが 増えると管理が破綻する問題があって、pecopercolを使えば解決出来そうと思ってやってみた。

仕組み

  • snippets用のファイル or sheetのスニペットファイルをpeco/percolで絞りこんで、クリップボードに送ったりして簡単に利用できるようにする

よく使うコマンドのスニペットファイルを用意

sheetの資産をそのまま利用も出来るんですが、今回は下記のような感じでファイルを~/.snippetsで用意。私が使ってるやつから一部抜粋。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# apache
tail -n 5000 /usr/local/apache2/logs/access_log | awk '{print $1}'  | sort | uniq -c | sort -gr | head -n 4
tail -n 5000 /usr/local/apache2/logs/access_log | awk '{print $2}'  | sort | uniq -c | sort -gr | head -n 4
tail -n 5000 /usr/local/apache2/logs/access_log | awk '{print $12}' | sort | uniq -c | sort -gr | head -n 4
tail -n 5000 /usr/local/apache2/logs/access_log | awk '{print $13}' | sort | uniq -c | sort -gr | head -n 4

# search
netstat -ltapn | grep ESTABLISHED | more
netstat -ltan | grep ":80 " | awk '{print $5}' | awk -F : '{print $4}' | sort | uniq -c | sort -nr | head
lsof -i:80

# dstat
dstat -Tclmdrn
dstat -Tclm
dstat -Tclr
dstat -Tclnd
dstat -Tcldr
dstat --top-cpu --top-cputime
dstat --top-io --top-bio
dstat --top-io-adv --top-bio-adv

# openssl
openssl x509 -noout -modulus -in *.crt | openssl md5
openssl rsa  -noout -modulus -in *.key | openssl md5
openssl req  -noout -modulus -in *.csr | openssl md5

# find
find ./ -daystart -ctime +2
find ./ -daystart -ctime -2

# date
date +%Y%m%d

peco/percol経由で利用出来るようにする

下記のようなのを、.zshrcに記載するか、peco-snippets.zshとかでファイルを作成してsourceして読み込む

1
2
3
4
5
6
7
8
function peco-snippets() {

    local SNIPPETS=$(grep -v "^#" ~/.snippets | peco --query "$LBUFFER" | pbcopy)
    zle clear-screen
}

zle -N peco-snippets
bindkey '^x^s' peco-snippets

snippetsファイルを用意せずに、sheetの資産を生かすなら、下記みたいな感じ。

1
2
3
4
5
6
7
8
function peco-snippets() {

    local SNIPPETS=$(cat ~/.sheets/* | peco --query "$LBUFFER" | pbcopy)
    zle clear-screen
}

zle -N peco-snippets
bindkey '^x^s' peco-snippets

で上の例だとCtrl+x, Ctrl+sでスニペットの一覧が出てくるのでpecoやpercolで絞ると pbcopyに渡されて、クリップボードに格納される。

Linux上とかでクリップボード使わずに、そのまま利用したい場合は下記みたいな感じ

1
2
3
4
5
6
7
8
function peco-snippets() {

    BUFFER=$(grep -v "^#" ~/.snippets | peco --query "$LBUFFER")
    zle clear-screen
}

zle -N peco-snippets
bindkey '^x^s' peco-snippets

実際に動かして見るとこんな感じ

便利になった!

私がUNIXという考え方にどっぶり浸かっているので、pecoやpercolのパイプで渡して処理させるってのは感覚的に分かりやすくて大変扱いやすい。