osquery とは
osquery とは OS の情報取得を SQL を書くことで実現するためのコマンドラインツールです。
Facebook によって開発され、Windows, maxOS, Linux で使用可能です。
試した環境
- CentOS 7
- osquery 3.2.6
なぜ osquery を使うのか
osquery
を使うことで従来の Linux コマンドでは困難だった OS の情報取得を改善することができます。
それを理解するために、まずは従来の Linux コマンドを使う場合にどのような問題が生じるのかを見てみます。
例えば Linux 上で httpd
という名前のプロセスを知りたい場合は pgrep
コマンドが使えます。
$ pgrep -fla httpd
14071 /usr/sbin/httpd -k start
14072 /usr/sbin/httpd -k start
14073 /usr/sbin/httpd -k start
14074 /usr/sbin/httpd -k start
14075 /usr/sbin/httpd -k start
14076 /usr/sbin/httpd -k start
14197 /usr/sbin/httpd -k start
14387 /usr/sbin/httpd -k start
23047 /usr/sbin/httpd -k start
またプロセスが使用しているポートを知りたい場合は lsof
コマンドが使えます。
$ sudo lsof -i:80 -P
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
httpd 14071 apache 3u IPv4 174132163 0t0 TCP *:80 (LISTEN)
httpd 14072 apache 3u IPv4 174132163 0t0 TCP *:80 (LISTEN)
httpd 14073 apache 3u IPv4 174132163 0t0 TCP *:80 (LISTEN)
httpd 14074 apache 3u IPv4 174132163 0t0 TCP *:80 (LISTEN)
httpd 14075 apache 3u IPv4 174132163 0t0 TCP *:80 (LISTEN)
httpd 14076 apache 3u IPv4 174132163 0t0 TCP *:80 (LISTEN)
httpd 14197 apache 3u IPv4 174132163 0t0 TCP *:80 (LISTEN)
httpd 14387 apache 3u IPv4 174132163 0t0 TCP *:80 (LISTEN)
httpd 23047 root 3u IPv4 174132163 0t0 TCP *:80 (LISTEN)
ここでもし 80 番ポートを使用しているプロセスの絶対パスを知りたいとなると 2 つのコマンドの出力結果から PID を突き合わせて情報を取得することになります。しかし Linux コマンドの出力結果はあまりパースしやすい形式で作られてないことが多いため、取得したい情報によっては複雑なシェル芸を書いてしまうことがあります。
こういうときに osquery
を使うと、SQL 構文を使って欲しい情報を簡単に得ることができます。
インストール
osquery
の Downloads ページの説明に従ってインストールします。
下記は CentOS で実行する場合です。その他の OS については Downloads の内容を参考にインストールしてください。
$ curl -L https://pkg.osquery.io/rpm/GPG | sudo tee /etc/pki/rpm-gpg/RPM-GPG-KEY-osquery
$ sudo yum-config-manager --add-repo https://pkg.osquery.io/rpm/osquery-s3-rpm.repo
$ sudo yum-config-manager --enable osquery-s3-rpm
$ sudo yum install osquery
使い方
httpd
という名前のプロセスの情報は、次のような SQL で取得できます。
$ osqueryi --json "SELECT pid, name, cmdline FROM processes WHERE name = 'httpd';"
[
{"cmdline":"/usr/sbin/httpd -k start","name":"httpd","pid":"14071"},
{"cmdline":"/usr/sbin/httpd -k start","name":"httpd","pid":"14072"},
{"cmdline":"/usr/sbin/httpd -k start","name":"httpd","pid":"14073"},
{"cmdline":"/usr/sbin/httpd -k start","name":"httpd","pid":"14074"},
{"cmdline":"/usr/sbin/httpd -k start","name":"httpd","pid":"14075"},
{"cmdline":"/usr/sbin/httpd -k start","name":"httpd","pid":"14076"},
{"cmdline":"/usr/sbin/httpd -k start","name":"httpd","pid":"14197"},
{"cmdline":"/usr/sbin/httpd -k start","name":"httpd","pid":"14387"},
{"cmdline":"/usr/sbin/httpd -k start","name":"httpd","pid":"23047"}
]
processes
というテーブルを参照してプロセスの情報が取得できます。実際にそのようなテーブルが DB に作られているわけではなく、あくまでも Linux コマンドのラッパのように振る舞います。
80 番ポートを使用しているプロセスの情報は、次のような SQL で取得できます。
(ポートの情報を取得するには root 権限が必要です)
$ sudo osqueryi --json "SELECT pid, port FROM listening_ports WHERE port = 80;"
[
{"pid":"23047","port":"80"}
]
80 番ポートを使用しているプロセスの絶対パスを取得したければ processes
テーブルと
listening_ports
テーブルを JOIN することで取得できます。
$ sudo osqueryi --json "SELECT pid, name, cmdline, port FROM listening_ports INNER JOIN processes USING(pid) WHERE port = 80;"
[
{"cmdline":"/usr/sbin/httpd -k start","name":"httpd","pid":"23047","port":"80"}
]
SQL はファイルに書くこともできます。ファイルをパイプで osqueryi
コマンドに渡すことで、引数に SQL を直接指定した場合と同じ結果を得ることができます。
list-httpd.sql
SELECT
pid,
name,
cmdline,
port
FROM
listening_ports
INNER JOIN processes USING(pid)
WHERE
port = 80;
$ cat list-httpd.sql | sudo osqueryi --json
[
{"cmdline":"/usr/sbin/httpd -k start","name":"httpd","pid":"23047","port":"80"}
]
processes, listening_ports
以外にどのようなテーブルを参照できるかは、公式サイトにある Schema ドキュメント にまとまっています。OS によって使用できるデーブルが異なるので注意してください。
まとめ
ナビタイムではサーバのデプロイ時に InSpec
を使ってサーバ構成のテストをしていますが、 InSpec
コードの煩雑さを減らす目的で osquery
を使っています。あらゆる情報が SQL と JSON で取得できるとかなりシンプルなチェックができるようになりますのでぜひお試しください。
参考
- osquery - 公式