前編はdataレベルのAuditログの出力方法まで紹介しました。
中編となる今回は、まず出力されたAuditログ中のIDを複合し、解析する方法をご紹介します。
次に本シリーズの最初のモチベーションであったMapR-DBへのアクセスに関するdataレベルのAudit機能とCDCの比較を行います。
Auditログ中のidの復号と解析
idの復号
出力されたAuditログはファイル名やユーザがMapR内部で利用するidで記録されているため、内容を把握する上ではこのidをファイル名に復号する必要があります。
復号にはexpandaudit
コマンドを利用して、以下のように実行します。
ここではクラスタ名ovのVolume名enable_auditで発生したAuditログをMFSの*/tmp*以下に出力します。
$ /opt/mapr/bin/expandaudit -cluster ov -volumename enable_audit -o /tmp/
$ hadoop fs -ls -R /tmp/
drwxr-xr-x - root root 2 2018-11-21 00:59 /tmp/27878493
drwxr-xr-x - root root 1 2018-11-21 00:59 /tmp/27878493/ov0
drwxr-xr-x - root root 7 2018-11-24 17:16 /tmp/27878493/ov0/5660
-rwxr-xr-x 3 root root 390421 2018-11-21 00:59 /tmp/27878493/ov0/5660/DBAudit.log-2018-11-20-001.json
-rwxr-xr-x 3 mapr mapr 70984 2018-11-24 17:16 /tmp/27878493/ov0/5660/DBAudit.log-2018-11-21-001.json
-rwxr-xr-x 3 mapr mapr 161876 2018-11-24 17:16 /tmp/27878493/ov0/5660/DBAudit.log-2018-11-24-001.part.json
-rwxr-xr-x 3 root root 490736 2018-11-21 00:59 /tmp/27878493/ov0/5660/FSAudit.log-2018-11-20-001.json
-rwxr-xr-x 3 mapr mapr 80291 2018-11-24 17:16 /tmp/27878493/ov0/5660/FSAudit.log-2018-11-21-001.json
-rwxr-xr-x 3 mapr mapr 459 2018-11-24 17:16 /tmp/27878493/ov0/5660/FSAudit.log-2018-11-22-001.json
-rwxr-xr-x 3 mapr mapr 423813 2018-11-24 17:16 /tmp/27878493/ov0/5660/FSAudit.log-2018-11-24-001.part.json
drwxr-xr-x - root root 1 2018-11-21 00:59 /tmp/27878493/ov1
drwxr-xr-x - root root 0 2018-11-24 17:16 /tmp/27878493/ov1/5660
Auditログが出力されているのが確認できました。
とりあえず中身を見てみましょう。
$ hadoop fs -cat /tmp/test/27878493/ov0/5660/FSAudit.log-2018-11-24-001.part.json
...
{"timestamp":{"$date":"2018-11-24T15:17:12.431Z"},"operation":"LOOKUP","user":"mapr","uid":5000,"ipAddress":"10.10.75.127","srcPath":"/enable_audit/set_audit","srcFid":"2305.32.397698","srcName":"100.yaml._COPYING_","VolumeName":"enable_audit","volumeId":27878493,"status":2}
{"timestamp":{"$date":"2018-11-24T15:17:12.433Z"},"operation":"CREATE","user":"mapr","uid":5000,"ipAddress":"10.10.75.81","parentPath":"/enable_audit/set_audit","parentFid":"2305.32.397698","childPath":"/enable_audit/set_audit/100.yaml._COPYING_","childFid":"2305.235.398104","childName":"100.yaml._COPYING_","VolumeName":"enable_audit","volumeId":27878493,"status":0}
{"timestamp":{"$date":"2018-11-24T15:17:12.440Z"},"operation":"WRITE","user":"mapr","uid":5000,"ipAddress":"10.10.75.127","srcPath":"/enable_audit/set_audit/100.yaml._COPYING_","srcFid":"2305.235.398104","VolumeName":"enable_audit","volumeId":27878493,"status":0}
{"timestamp":{"$date":"2018-11-24T15:17:12.440Z"},"operation":"LOOKUP","user":"mapr","uid":5000,"ipAddress":"10.10.75.127","srcPath":"/enable_audit/set_audit","srcFid":"2305.32.397698","srcName":"100.yaml","VolumeName":"enable_audit","volumeId":27878493,"status":2}
{"timestamp":{"$date":"2018-11-24T15:17:12.441Z"},"operation":"RENAME","user":"mapr","uid":5000,"ipAddress":"10.10.75.81","srcPath":"/enable_audit/set_audit","srcFid":"2305.32.397698","dstPath":"/enable_audit/set_audit","dstFid":"2305.32.397698","srcName":"100.yaml._COPYING_","dstName":"100.yaml","VolumeName":"enable_audit","volumeId":27878493,"status":0}
{"timestamp":{"$date":"2018-11-24T15:17:15.834Z"},"operation":"CHPERM","user":"mapr","uid":5000,"ipAddress":"10.10.75.81","srcPath":"/enable_audit/set_audit/100.yaml._COPYING_","srcFid":"2305.235.398104","permissions":"0777","VolumeName":"enable_audit","volumeId":27878493,"status":0}
{"timestamp":{"$date":"2018-11-24T15:17:19.001Z"},"operation":"DELETE","user":"mapr","uid":5000,"ipAddress":"10.10.75.127","parentPath":"/enable_audit/set_audit","parentFid":"2305.32.397698","childPath":"/enable_audit/set_audit/100.yaml","childFid":"2305.235.398104","childName":"100.yaml","VolumeName":"enable_audit","volumeId":27878493,"status":0}
...
ユーザID, ファイルパスが復元されていますね。
前回の記事で/enable_audit/set_audit/
と/enable_audit/non_set_audit/
ディレクトリを対象に操作を行いましたが、Auditログに記載が残ったのは/enable_audit/set_audit/
への操作のみでした。
こちらも設定どおりですね。
$ hadoop fs -cat /tmp/tmp/27878493/ov0/5660/FSAudit.log-2018-11-24-001.json | grep set_audit | wc -l
942
$ hadoop fs -cat /tmp/tmp/27878493/ov0/5660/FSAudit.log-2018-11-24-001.json | grep non_set_audit | wc -l
0
ところで、ファイルパスは expandaudit指定パス
/VolumeID
/ホスト名
/MFSポート
/Auditファイル名
.log-YYYY-mm-DD-Index
.json のような形式を取ります。
Auditログは実際にクライアントから処理を受け付けてデータ処理を行ったホストのローカルVolume上で記録されますが、expandaudit
を実行することで引数に受け取ったパス上に出力されます。
また、出力先のVolumeID
の下位のディレクトリに上記の処理を受け付けたホスト名がディレクトリとして記録されます。
今回行った処理はデータの生成や削除処理のため、マスターコンテナを持つノードに処理が集中しますが、読み込みのみの処理を行う場合には、負荷分散のためレプリカを持つノードにもアクセスが発生しますので、Auditの出力先もレプリカを持つ全てのノードが対象となります。
Index
についてはMFSを再起動するたびにローテーションされますので、MFSを稼働しっぱなしの場合は001のみとなります。
また、expandaudit
は出力パスに存在する復元対象のファイルが存在する場合、このファイルが前日までのデータの場合、もしくは当日のデータでも既にローテーションされ最新のIndexがついていない場合、読み込みは行いません。
最新のIndexがつく当日のデータに関しては、expandaudit
を何度実施しても毎回ファイル全てを読み込みますが、この場合出力されたファイルの拡張子はpart.json
となります。
そのため、例えばMFSの再起動が発生しない状況で1日1回expandaudit
を実行するようなルーチンを組んだ場合、前日までのデータの読み込みは発生しません。
データの解析
idの復号が終わったところで解析に移りたいと思います。
といっても単なるjsonファイルなので、どのようにでも解析できますね。
例えばDrillを使うと、以下のようなクエリで内容を参照できます。
$ sqlline -u jdbc:drill:drillbit=ov0 -n mapr -p mapr
0: jdbc:drill:drillbit=ov0> select `timestamp`, `user`, `srcPath`, `VolumeName` from dfs.`/tmp/27878493/*/5660/FSAudit.log-*.json` where `operation` = 'WRITE' and `timestamp` > '2018-11-25 08:00:00';
+--------------------------+-------+----------------------------------+---------------+
| timestamp | user | srcPath | VolumeName |
+--------------------------+-------+----------------------------------+---------------+
| 2018-11-25 08:34:21.052 | mapr | /enable_audit/set_audit/7.yaml | enable_audit |
| 2018-11-25 08:34:21.206 | mapr | /enable_audit/set_audit/5.yaml | enable_audit |
| 2018-11-25 08:34:21.47 | mapr | /enable_audit/set_audit/1.yaml | enable_audit |
| 2018-11-25 08:34:21.491 | mapr | /enable_audit/set_audit/6.yaml | enable_audit |
| 2018-11-25 08:34:21.673 | mapr | /enable_audit/set_audit/10.yaml | enable_audit |
| 2018-11-25 08:34:21.676 | mapr | /enable_audit/set_audit/3.yaml | enable_audit |
| 2018-11-25 08:34:21.869 | mapr | /enable_audit/set_audit/4.yaml | enable_audit |
| 2018-11-25 08:34:22.047 | mapr | /enable_audit/set_audit/9.yaml | enable_audit |
| 2018-11-25 08:34:22.116 | mapr | /enable_audit/set_audit/8.yaml | enable_audit |
| 2018-11-25 08:34:22.161 | mapr | /enable_audit/set_audit/2.yaml | enable_audit |
| 2018-11-25 08:34:22.173 | mapr | /enable_audit/set_audit/0.yaml | enable_audit |
+--------------------------+-------+----------------------------------+---------------+
11 rows selected (0.346 seconds)
必要に応じてワイルドカードを使えば、クラスタ中のどのノードで実行しているかを意識せずに済みます。
MapR-DBのAudit機能とCDCの比較
さて、本編の主題であったはずのChangeDataCapture(CDC)機能との比較についてまとめましょう。
CDCの紹介時に行ったものと同様の処理をしてみます
mapr@ov0[3920] mapr dbshell
====================================================
* MapR-DB Shell *
* NOTE: This is a shell for JSON table operations. *
====================================================
Version: 6.0.1-mapr
MapR-DB Shell
maprdb mapr:> insert /enable_audit/set_audit/db/test --value '{"_id":"3011", "USERNAME":"王騎", "total_score":286, "PROP":{"intellligence":95, "power":98, "lead":93}}'
Document with id: ""3011"" inserted.
maprdb mapr:> update /user/mapr/db/test --id "3011" --m '{ "$set":[{"USERNAME":"王騎(おうき)"},{"total_score":290} ] }'
The table specified by the path '/user/mapr/db/test' was not found.
maprdb mapr:> update /enable_audit/set_audit/db/test --id "3011" --m '{ "$set":[{"USERNAME":"王騎(おうき)"},{"total_score":290} ] }'
Document with id: "3011" updated.
maprdb mapr:> delete /enable_audit/set_audit/db/test --id "3011"
Document with id: "3011" deleted.
CDCには紹介時と同様、テーブルへの変更の具体的な値が補足されています。
$ java -cp target/maprdb-cdc-sample-1.0-SNAPSHOT.jar:`mapr clientclasspath` com.mapr.samples.db.cdc.json.DumpCDC /user/mapr/stream/cdc cdcTopic1
==== Start DumpCDC with /user/mapr/stream/cdc:cdcTopic1===
{
"type" : RECORD_INSERT,
"documentId : 3011,
"recordOpTime : 1543500728818,
"recordServerOpTime : 1543500728818,
"insertData" : {
"PROP : {"intellligence":95,"lead":93,"power":98},
"USERNAME : 王騎,
"total_score : 286.0 }
}
{
"type" : RECORD_UPDATE,
"documentId : 3011,
"recordOpTime : 1543500874960,
"recordServerOpTime : 1543500874960,
"updateData" : {
USERNAME : 王騎(おうき)
}
"updateData" : {
total_score : 290.0
}
}
{
"type" : RECORD_DELETE,
"documentId : 3011,
"recordOpTime : 1543500907168,
"recordServerOpTime : 1543500907168,
}
では次にAuditログを確認します
$ /opt/mapr/bin/expandaudit -cluster ov -volumename enable_audit -o /tmp/
$ hadoop fs -ls -R /tmp/27878493/ | grep DBAudit
...
〜中略〜
...
-rwxr-xr-x 3 mapr mapr 21383 2018-11-29 09:20 /tmp/27878493/ov0/5660/DBAudit.log-2018-11-29-001.part.json
-rwxr-xr-x 3 mapr mapr 528 2018-11-29 09:20 /tmp/27878493/ov1/5660/DBAudit.log-2018-11-29-001.part.json
-rwxr-xr-x 3 mapr mapr 527 2018-11-29 09:20 /tmp/27878493/ov2/5660/DBAudit.log-2018-11-29-001.part.json
$ sqlline -u jdbc:drill:drillbit=ov0 -n mapr -p
0: jdbc:drill:drillbit=ov0> select `timestamp`,`operation`,`user`,`uid`,`ipAddress`,`VolumeName`, `volumeId`, `tablePath` from dfs.`/tmp/27878493/ov0/5660/DBAudit.log-2018-11-29-001.part.json` order by `timestamp`;
+--------------------------+------------------+-------+-------+---------------+---------------+-----------+----------------------------------+
| timestamp | operation | user | uid | ipAddress | VolumeName | volumeId | tablePath |
+--------------------------+------------------+-------+-------+---------------+---------------+-----------+----------------------------------+
| 2018-11-29 08:34:03.467 | DB_TABLECREATE | mapr | 5000 | 10.10.75.81 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:34:03.516 | DB_CFSCAN | mapr | 5000 | 10.10.75.127 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:34:03.52 | DB_TABLEINFO | mapr | 5000 | 10.10.75.81 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:34:03.526 | DB_CFCREATE | mapr | 5000 | 10.10.75.127 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:34:03.527 | DB_CFSCAN | mapr | 5000 | 10.10.75.81 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:34:03.53 | DB_TABLEINFO | mapr | 5000 | 10.10.75.127 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:35:54.68 | DB_CFSCAN | mapr | 5000 | 10.10.75.81 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:35:54.683 | DB_TABLEINFO | mapr | 5000 | 10.10.75.127 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:35:54.715 | DB_CFSCAN | mapr | 5000 | 10.10.75.127 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:36:02.828 | DB_CFSCAN | mapr | 5000 | 10.10.75.98 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:36:09.575 | DB_PUT | mapr | 5000 | 10.10.75.98 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:36:09.575 | DB_PUT | mapr | 5000 | 10.10.75.98 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:36:09.575 | DB_PUT | mapr | 5000 | 10.10.75.98 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:36:09.575 | DB_PUT | mapr | 5000 | 10.10.75.98 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:36:09.575 | DB_PUT | mapr | 5000 | 10.10.75.98 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:37:26.937 | DB_CFSCAN | mapr | 5000 | 10.10.75.81 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:37:26.937 | DB_TABLEINFO | mapr | 5000 | 10.10.75.127 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:37:26.947 | DB_CFSCAN | mapr | 5000 | 10.10.75.127 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:37:27.194 | DB_INDEXADD | mapr | 5000 | 10.10.75.81 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
| 2018-11-29 08:37:27.194 | DB_REGIONLOOKUP | mapr | 5000 | 10.10.75.127 | enable_audit | 27878493 | /enable_audit/set_audit/db/test |
...
(省略)
このように、Auditログの中ではDB_PUTやDB_INDEXADDなどDB操作のメタ情報が記録されていますが、CDCのように具体的な値については捕捉していません。
一方でどのユーザがどのVolumeのどのテーブルにアクセスしたか、といったCDCでは取得できない情報を包括的に取得することができます。
このようにCDCが具体的なデータ更新分の解析や活用を主眼としている一方で、Auditログがデータアクセス分析やコンプライアンス実現のための機能として向いていると言うことができます。
dataレベルのAudit機能が具体的にどのようなデータ操作を記録できるかについては、こちらのページにまとめられております。
また、上記ページの表のOperation Name to use for Selective AuditingカラムがYのオペレーションに関しては、監視対象とするかどうかを制御することが可能です。
制御の際にはVolumeの-dataauditops
オプションの設定により選択可能となり、この結果はvolume info
のenableddataauditoperations
,disableddataauditoperations
に反映されます。
$ maprcli volume info -name enable_audit -json
{
"timestamp":1544623211387,
...
"coalesceInterval":1,
"enableddataauditoperations":"setattr,chown,chperm,chgrp,getxattr,listxattr,setxattr,removexattr,read,write,create,delete,mkdir,readdir,rmdir,createsym,lookup,rename,createdev,truncate,tablecfcreate,tablecfdelete,tablecfmodify,tablecfScan,tableget,tableput,tablescan,tablecreate,tableinfo,tablemodify,getperm,getpathforfid,hardlink",
"disableddataauditoperations":"getattr",
}
ここで例えばgetattr
を監視対象に入れ、tableinfo
, getperm
を監視対象から外すには以下のようにコマンドを実行します。
$ maprcli volume modify -name enable_audit -dataauditops +getattr,-tableinfo,-getperm
$ maprcli volume info -name enable_audit -json
{
...
"enableddataauditoperations":"getattr,setattr,chown,chperm,chgrp,getxattr,listxattr,setxattr,removexattr,read,write,create,delete,mkdir,readdir,rmdir,createsym,lookup,rename,createdev,truncate,tablecfcreate,tablecfdelete,tablecfmodify,tablecfScan,tableget,tableput,tablescan,tablecreate,tablemodify,getpathforfid,hardlink",
"disableddataauditoperations":"tableinfo,getperm",
...
変更されていますね。
さて、ここまで紹介してきたCDCとAuditの比較結果をまとめてみると、以下の様になりました。
CDC | Audit with expandaudit | |
---|---|---|
リアルタイム性 | ○ | ☓(Audit Streamについては後編) |
データ | 実データ | メタデータ |
gateway | 必要 | 必要なし |
データ形式 | CDC | json(Audit StreamではConsumeRecords) |
解析プログラム | CDC APIを利用したアプリケーション | Drillなど |
蓄積場所 | gatewayで指定したクラスタのストリーム | 同一クラスタ上のMFS |
制御単位 | テーブル | Volume, ディレクトリ, ファイル, DB, ES |
まとめ
本編ではAuditログのidの複合から、MapR-DBのAudit機能とCDCとの比較を行いました。
次回のAudit機能シリーズの最終編としては、リアルタイムでのAuditログの解析を可能とする、Audit stream機能について紹介します。