osquery+Kolide Fleetで大量のサーバから情報を取得する
「Linux Kernelに脆弱性が見つかった… 管理している大量のサーバのカーネルバージョンを取得してリスト化したい…」 そんな時にあなたならどうしますか? 1台1台SSHでログインして uname -r
を叩くシェルスクリプトを作るのは汎用性が有りますが、遅い・エラーハンドリング・ホストのリストの管理・権限の管理等、様々な問題にぶつかると思います。
今回は、そんな問題を解決するためのツール達を紹介します。
osquery
osqueryはSQLでマシンの様々な情報を取得するためのツールです。 ユーザが理解しやすいSQLで、セキュリティ・監査・DevOps等をサポートします。 Facebookが開発しており、コードはGithub上で公開されています。 対応プラットフォームはLinux, Windows, macOSと幅広いです。 osquery単体ではインストールした1台のマシンに対してのみクエリを行うことが出来ます。
https://github.com/osquery/osquery
まずはインストールして試してみましょう。 .rpm
.tar.gz
.msi
などのパッケージや、brew, aptなどの各プラットフォーム向けのリポジトリが用意されています。 私は手っ取り早く試したかったので、 .tar.gz
を手元のUbuntuマシンで展開しました。
$ wget https://pkg.osquery.io/linux/osquery-3.3.2_1.linux_x86_64.tar.gz
$ mkdir osquery
$ tar xf osquery-3.3.2_1.linux_x86_64.tar.gz -C ./osquery
インストールを行うと、3つのコマンドが利用可能になります。
- osqueryi
- インタラクティブなシェルを提供するCLIコマンド
- 完全に独立して動作し、デーモンと通信することもなくマシンの情報を収集する
- 管理者権限として実行する必要はない
- osqueryd
- 設定ファイルに記述されたクエリを定期的に実行するデーモン
- OSの状態変化を記録することが出来る
- 今回は使用しない
- osqueryctl
- osquerydの開始・終了・設定のチェックが行える
- 今回は使用しない
今回はosqueryi単体で試してみます。 まずは手始めにOSのバージョンを取得してみます。 ここでは引数にSQLを渡しますが、引数無しで実行することでインタラクティブシェルに入ることも出来ます。
$ osqueryi "SELECT * FROM os_version;"
+--------+----------------------------+-------+-------+-------+-------+----------+---------------+----------+
| name | version | major | minor | patch | build | platform | platform_like | codename |
+--------+----------------------------+-------+-------+-------+-------+----------+---------------+----------+
| Ubuntu | 16.04.1 LTS (Xenial Xerus) | 16 | 4 | 0 | | ubuntu | debian | xenial |
+--------+----------------------------+-------+-------+-------+-------+----------+---------------+----------+
利用可能なテーブルについての情報は、公式サイトのリファレンスで確認します。 sysctlなどのOS関連・debなどのパッケージマネージャ・Dockerなどのミドルウェアを始めとする様々な情報が取得可能であることが分かります。https://osquery.io/schema
SQLで利用可能な構文は、SQLiteで利用可能なものです。 必要であればJOIN等も行うことが出来ます。http://www.sqlite.org/lang.html
osqueryを複数サーバで実行したい
今紹介したosqueryは、単一のマシンの情報を取得するためのツールでした。 例えば100台のサーバにインストールすると、SQLでOSの情報を一括で取得できて便利そうです。 そういったニーズに応えるのが、Kolide FleetとKolide Launcherです。
各コンポーネントの関係・通信の流れはこのようになります。
- ユーザはブラウザを使用してクエリの入力・対象マシンの選択を行う
- Kolide Fleetが対象マシンに対してクエリを送信する
- 各マシンで動作するKolide Launcherが、osqueryにクエリする
- クエリ結果をKolide Fleetに返却する
- 複数マシンからのレスポンスを集計し、ユーザのブラウザに返却する
Kolide Fleet
Kolideは利便性を重視したセキュリティ監査のためのプラットフォームです。 2019年7月現在、1台のデバイス・月額あたり6USDの有償サービスです。 Kolide Launcher
というエージェントをOSにインストールし、マシン毎の数千の情報をクラウド上のサーバに送信することで、ダッシュボード・Slackなどを通じて情報を得ることが出来ます。 例えば、従業員の全てのPCにインストールすることで、「ディスクを暗号化していないマシン」「Chromeで危険な拡張機能を入れているマシン」などのリストを取得することが可能です。
こうしたOS上の情報を収集するために、先ほど紹介したosqueryを使用しています。 決められた情報を定期的に収集する・必要な時に迅速にマシンから任意の情報を収集するという、2つのワークロードへ非常にマッチしていると感じます。
Kolideの機能を詳しく知りたい場合は、公式サイトから無償体験が行えるようです。 https://kolide.com/
この便利なプラットフォームであるKolideの機能を減らして自分のオンプレ環境で動かせるようにしたOSSがKolide Fleetです。 先程紹介したようなSlack連携などの便利そうな機能は無いものの、複数マシンのosqueryに対してSQLを送信して情報を収集することができます。
Kolide Fleetのインストール
OSS版のKolide Fleetをdocker-composeで動作させてみましょう。 動作条件は以下のとおりです。
- Docker, Docker Compose
- サーバへのドメイン名の割当 (ここではkolide-fleet.example.comとします)
- TLS証明書
TLSの利用が必須なので、自己署名証明書を生成します。 本番環境であれば、Let's Encrypt等を利用できるかと思います。
$ mkdir keys
$ openssl genrsa 2048 > keys/server.key
$ openssl req -new -key keys/server.key > keys/server.csr
$ openssl x509 -days 3650 -req -signkey keys/server.key < keys/server.csr > keys/server.crt
以下は必要となるDockerComposeファイル・設定ファイルです。 パスワード等は仮で設定しています。実際に試す際は変更を推奨します。
# docker-compose.yml
version: '3'
services:
mysql:
image: mysql:5.7
command: mysqld --datadir=/tmp/mysqldata
environment:
MYSQL_ROOT_PASSWORD: toor
MYSQL_DATABASE: kolide
MYSQL_USER: kolide
MYSQL_PASSWORD: kolide
TZ: 'Asia/Tokyo'
volumes:
- mysqldata:/tmp
expose:
- "3306"
redis:
image: redis:5.0
expose:
- "6379"
fleet:
image: kolide/fleet:latest
command: sh -c "echo '\n' | /usr/bin/fleet prepare db --config=/tmp/kolide.yml && /usr/bin/fleet serve --config=/tmp/kolide.yml"
depends_on:
- mysql
- redis
volumes:
- .:/tmp
ports:
- "443:443"
volumes:
mysqldata: {}
# kolide.yml
mysql:
address: mysql:3306
database: kolide
username: kolide
password: kolide
redis:
address: redis:6379
server:
address: 0.0.0.0:443
tls: true
key: /tmp/keys/server.key
cert: /tmp/keys/server.crt
logging:
json: true
debug: false
auth:
jwt_key: changeme
docker-compose up
でサービスを起動後、ブラウザで https://kolide-fleet.example.com/
のようにアクセスすると管理画面が表示されます。 各種登録を済ませるとホスト一覧画面が表示されます。
Add New Host
をクリックして Enroll Secret
を取得しておきます。
Kolide Launcher
クラウドサービスのKolideや、オンプレ環境のKolide Fleetに情報を送信するためのエージェントがKolide Launcherです。 osqueryのデーモンであるosquerydとKolideの通信を橋渡しするコンポーネントです。 大規模な利用でのインストール・更新・設定が簡単になります。
こちらは残念ながらOSSとしては便利なインストーラー等が用意されていないので、GithubのRelease上からZIPファイルをダウンロードしてインストールします。 各プラットフォーム向けの launcher
実行ファイル・ osqueryd
osquery-extension.ext
のデーモン等が同包されています。
https://github.com/kolide/launcher/releases
$ wget https://github.com/kolide/launcher/releases/download/0.10.2/launcher_0.10.2.zip
$ unzip launcher_0.10.2.zip
$ ls launcher_0.10.2/linux/
launcher osqueryd osquery-extension.ext
launcherの起動を行うには、先程建てたKolide Fleetサーバのホスト名とEnroll Secretを指定する必要があります。 今回はサーバ証明書に自己署名証明書を導入しているので --insecure
オプションを追加していますが、本番環境であれば外すべきでしょう。
launcher \
--hostname=kolide-fleet.example.com:443 \
--enroll_secret=32IeN3QLgckHUmMD3iW40kyLdNJcGzP5 \
--insecure
設定がうまく行っていれば、すぐにKolide Fleetの管理画面にホストが表示されます。 数台入れておくとクエリを行う際に楽しいので、数台サーバを用意することをおすすめします。
ダッシュボードの操作
まずは単純なクエリを実行してみましょう。 QUERY
タブ→CREATE NEW QUERY
ボタンをクリックします。
デフォルトで入力されている SELECT * FROM osquery_info
を全てのノードに対して実行してみましょう。 Select Targets
で All Hosts
の右にある +
ボタンをクリックします。 あとは RUN
ボタンをクリックすれば全てのノードでSQLが実行されます。
試しに60台ほどのマシンで試してみましたが、クエリは数秒で完了しました。
クエリを書く
osqueryでは、sysctlなどのOS関連・debなどのパッケージマネージャ・Dockerなどのミドルウェアを始めとする様々な情報が取得可能です。 Kolide Fleetでは、osqueryが扱うその全てが取得可能です。 テーブルの一覧はこちらです。https://osquery.io/schema/
クエリの例を何個か載せておきます。
SELECT * FROM os_version; -- OSバージョンを取得する
SELECT * FROM docker_containers; -- Docker上で動作しているコンテナを取得する
SELECT * FROM system_controls where name = "vm.max_map_count"; -- カーネルパラメータを取得する
SELECT * FROM file WHERE path = '/etc/nginx/nginx.conf'; -- 指定されたパスのファイル情報を取得する
冒頭に書いていたLinux Kernelのバージョンを調べるためのSQLはこのようになります。
SELECT version FROM kernel_info;
最後に
弊社で提供しているIoTサービスである「sakura.io」のサーバ管理の省力化を行うために調べていた結果、見つけたプロダクトがosquery・それを活用するKolide Fleetでした。 プロダクトの成長と共に徐々にサーバの台数も増加しており、一部のミドルウェア・ライブラリのバージョンが揃っていない場合が有りました。 そういった場合に、エンジニアが数分で目的の情報を手軽に得ることが出来る環境が整いました。 メトリクス監視・ログ収集などのツールと組み合わせることで、障害発生時のオペレーションも効率的に行えるようになると感じます。
さくらインターネットでは、sakura.ioを始めとした様々なサービスを作る仲間を募集しています。 興味が有る方は https://www.sakura.ad.jp/recruit/ から採用情報をチェックしてください!