インスタンスを立ち上げてから、みなさんに使ってもらうのは良いんですが、何を操作したかわからないのは、やばいですよね。

なので、Linuxの監査ログをカスタムログとして採取して管理しましょう。

OracleLinuxの場合、デフォルトでエージェントがセットアップされているので、簡単ですね。


ロギング-エージェント構成より、エージェント構成を作成します。

入力タイプ:ログパス

ファイルパス:/var/log/audit/audit.log

高度なパーサー・オブションで、AUDITDを指定することで、良い感じでJSONに変換してくれます。

最後にログの保存先を指定します。

これだけで、ログを吸い上げることが出来るんですが、一定期間で捨てられてしまいます。

なので、ObjectStorageにでも保管しておきましょう。

こういう時は、サービスコネクタを使うと出来るそうです。

どういうことかと言うと、OracleLinuxにインストールされているエージェントで、/var/log/audit/audit.log の中身をJSONに変換してロギングサービスに吸い上げます。

そして、サービスコネクタにより、その中身をObjectStorageへ一定間隔毎に出力します。

サービスコネクタのソースを/var/log/audit/audit.logを吸い上げたログにして、ターゲットをオブジェクトストレージにすると実現出来ます。

構築して、しばらくすると、ターゲットに指定したオブジェクトストレージにgz形式でファイルが作成されていきます。

後は、オブジェクトストレージにライフサイクルポリシーでも指定しておいて、自動削除すれば完成ですな。

あっ、ポリシーの設定を忘れてました。

allow any-user to manage objects in compartment hoge where all {request.principal.type= 'serviceconnector', request.principal.compartment.id='ocid1.compartment.oc1..aaaaaaaab2rjf3lkitnzo4tzax5ub2sec7lzwi7nfllpeo4xhogehoge'}

 


これだけで、とりあえず基本的なログを吸い上げれるのですが、ログの中身がいまいちです。

/var/log/audit/audit.log に、もっと色々な情報を詰め込みたいですよね。

そういう時は、auditctl を使います。

詳しいことは、Googleさんにでも尋ねて下さい。

auditctl で、色々追加するとログに記録されていくのですが、不揮発の設定にならないので、/etc/audit/rules.d/ に、定義ファイルを作成しておきましょうね。

以下のような定義を入れておくと、実行したコマンドが記録されていきます。

-a exit,always -F arch=b64 -F uid!=0 -F gid!=985 -S execve -k execute

これで、ObjectStorageへ記録されるのですが、この内容だけ分けてObjectStorageへ記録したい時は、サービスコネクタのログ・フィルタ・タスクで、data."body.key"='execute' を指定すると分けることが出来ます。


さて、コマンド実行の記録は取れたのですが、やっぱりキーログ的な物もほしいですか。

ということで、以下のファイルに追記してみましょう。

/etc/pam.d/system-auth
/etc/pam.d/password-auth

session     required                                     pam_tty_audit.so disable=* enable=*

これで、/var/log/audit/audit.log に、どんどん、キー操作が吸い上げられます。

中身は、バイナリエンコードされているので、見てもわかりにくいので、以下のコマンドで確認します。

aureport --tty

ということは、ObjectStorageに記録されている情報もわかりにくいですよね。

こんな時は、サービスコネクタで、ファンクション・タスクを使いデコードしちゃいましょう。

まずは、ファンクションを作成します。

 

import io
import json
import logging
import re
 
from fdk import response
 
# Decode tty output data
def decode_tty_data(org_data):
    # ユーザーIDで分割する
    hex_data=org_data.split('UID')[0][:-1]
 
    # 16進数データをバイト配列に変換
    bytes_data = bytes.fromhex(hex_data)
    # バイト配列をASCII文字列にデコード
    return bytes_data.decode('utf-8', errors='ignore')
 
# 制御コード置き換え
rep_dict = {
    r"\x00":"",
    r"\x04":"",
    r"\x07":"<bel>",
    r"\x08":"<bs>",
    r"\x0a":"<lf>",
    r"\x0d":"<cr>",
    r"\x1b":"<esc>",
    r"\x20":" ",
    r"\n":"<ret>",
    r"\t":"<tab>",
    r"\x7f":"<del>",
            }
 
def replace_control(srcstr):
    replaced_string = srcstr
    for k,v in rep_dict.items():
        replaced_string = re.sub("[{0}]+".format(k),v,replaced_string)
    return replaced_string
 
# エントリ
def handler(ctx, data: io.BytesIO = None):
    instr = "" 
    try:
        instr = data.getvalue().decode('utf-8')
 
        # JSONオブジェクトを解析
        body = json.loads(instr)
        # 複数行対応
        for rec in body:
            # 
            rec["data"]["body.datadecode"] = replace_control(decode_tty_data(rec["data"]["body.data"]))
 
    except (Exception, ValueError) as ex:
        logging.getLogger().info(instr)
        return str(ex)
 
    return response.Response(
        ctx, response_data=json.dumps(body, ensure_ascii=False),
        headers={"Content-Type": "application/json"}
    )

 

次に、キーログを分けます。

サービスコネクタのログ・フィルタ・タスクで、data."header.type"='TTY' を指定します。

さらにタスクの構成で、作成したファンクションを指定します。

後は、ターゲットを指定すればOkです。

あっ後、ポリシー

allow any-user to use functions-family in compartment hoge where all {request.principal.type='serviceconnector',  request.principal.compartment.id='ocid1.compartment.oc1..aaaaaaaab2rjf3lkitnzo4tzax5ub2sec7lzwi7nfllpeo4xhogehoge'}

こんな感じで、キーログの中身も良い感じで取得出来るので、どんどん監査していきましょうよ

 

Joomla templates by a4joomla