ノート:

カスタム時間範囲のCSV形式でOCI監査ログをエクスポートします

イントロダクション

OCI監査ログは、Oracle Cloud Infrastructure Auditサービスによって発行されるイベントに関連しています。これらのログは、OCIコンソールの「ロギング監査」ページから取得するか、残りのログとともに「検索」ページで検索できます。Oracle Cloud Infrastructure (OCI)監査ログは、Oracle Cloudコンソールから最大14日間のカスタム時間範囲のJSON形式でエクスポートできます。

このチュートリアルでは、14日を超える期間の監査ログをCSV形式でエクスポートするためのカスタム・スクリプトをデプロイする方法について学習します。

ノート: 監査ログの最大保存期間は365日のみです。

目的

カスタムの時間範囲(365日未満)について、OCI監査ログをCSV形式でエクスポートするためのカスタムPythonスクリプトをデプロイします。

前提条件

タスク1: カスタムPythonスクリプトのデプロイ

  1. コマンドを使用して、PythonがVMにインストールされているかどうかを確認します。

    python3 –-version
    
  2. コマンドを使用してPandasライブラリをインストールします。

    pip3 install pandas
    
  3. 新しいディレクトリを作成し、スクリプトをデプロイするディレクトリに変更します。

    mkdir <directory-name>
    cd <directory-name>
    
  4. main.pyという名前のファイルを作成し、任意のエディタを使用してそのファイルを編集します(ここではvimエディタが使用されています)。

    touch main.py
    vim main.py
    
  5. 次に示すように、main.pyファイル内にスクリプトの内容をコピーして貼り付け、:xと入力して Enterをクリックしてファイルの内容を保存します。

    import pandas as pd
    import csv
    import os
    import datetime
    from datetime import timedelta,date
    import subprocess
    import json
    import sys
    import getopt
    
    def myfunc(argv):
    
        START_DATE = ""
        END_DATE = ""
        COMPARTMENT_ID = ""
        arg_help = "\nUsage:\n\npython3 main.py -s <log_start_date in YYYY-MM-DD Format> -e <log_end_date in YYYY-MM-DD Format> -c <Compartment_ID>\n".format(argv[0])
        try:
            opts, args = getopt.getopt(argv[1:],"hs:e:c:")
        except:
            print("\nenter valid argument values. Try -h option with script to know the usage.\n")
            sys.exit(2)
    
        for opt, arg in opts:
            if opt in ("-h"):
                print(arg_help)  # print the help message
                sys.exit(2)
            elif opt in ("-s"):
                START_DATE = arg
            elif opt in ("-e"):
                END_DATE = arg
            elif opt in ("-c"):
                COMPARTMENT_ID = arg
    
        INC = -1
        year1, month1, day1 = map(int, START_DATE.split('-'))
        DATE1 = datetime.date(year1, month1, day1)
        year2, month2, day2 = map(int, END_DATE.split('-'))
        DATE2 = datetime.date(year2, month2, day2)
        NUM_DAYS = DATE2 - DATE1
        NUM_DAYS = NUM_DAYS.days
    
    # Function for converting JSON to .CSV format
    
        def convert_csv():
    
            with open('out.json', 'r') as file:
                data = json.load(file)
            datetimez = []
            compartmentID = []
            compartmentName = []
            message = []
            tenantId = []
            userAgent = []
            path = []
            ingestedtime = []
            type = []
            id = []
            for ele in data['data']['results']:
                datetimez.append(ele['data']['datetime'])
                compartmentID.append(ele['data']['logContent']['data']['compartmentId'])
                compartmentName.append(ele['data']['logContent']['data']['compartmentName'])
                message.append(ele['data']['logContent']['data']['message'])
                tenantId.append(ele['data']['logContent']['data']['identity']['tenantId'])
                userAgent.append(ele['data']['logContent']['data']['identity']['userAgent'])
                path.append(ele['data']['logContent']['data']['request']['path'])
                ingestedtime.append(ele['data']['logContent']['oracle']['ingestedtime'])
                type.append(ele['data']['logContent']['type'])
                id.append(ele['data']['logContent']['id'])
            finaldate = []
            for ts in datetimez:
                finaldate.append(datetime.datetime.fromtimestamp(int(ts) / 1000).strftime('%Y-%m-%d %H:%M:%S'))
    
            output = zip(finaldate, compartmentID, compartmentName, message, tenantId, userAgent, path, ingestedtime, type, id)
            output = list(output)
            df = pd.DataFrame(output)
            df.to_csv('/tmp/out.csv', header=False , mode='a',index=False)
            return None
    
    # Check and validate the .CSV file in the /tmp directory
    
        os.system("touch /tmp/out.csv" )
        os.remove("/tmp/out.csv")
        header=['Date-Time', 'CompartmentID', 'CompartmentName', 'Message', 'TenantId', 'UserAgent', 'Path', 'Ingested-Time', 'Type', 'ID']
        data = []
        with open('/tmp/out.csv', 'a') as f:
            writer = csv.writer(f)
            writer.writerow(header)
            writer.writerows(data)
    
    # Block for saving Audit Logs in JSON format to out.json file    
    
        for i in range(INC, NUM_DAYS):
            print("\ncollecting logs for", DATE1)
            p = subprocess.Popen(''' oci logging-search search-logs --search-query 'search "''' + str(COMPARTMENT_ID) + '''/_Audit" | sort by datetime desc' --time-start ''' + str(DATE1) + '''"T00:00:00Z" --time-end ''' + str(DATE1) + '''"T23:59:00Z" > out.json ''', shell=True, stdout=subprocess.PIPE)
            (output, err) = p.communicate()
            convert_csv()
            PAG = subprocess.check_output(''' oci logging-search search-logs --search-query 'search "''' + str(COMPARTMENT_ID) + '''/_Audit" | sort by datetime desc' --time-start ''' + str(DATE1) + '''"T00:00:00Z" --time-end ''' + str(DATE1) + '''"T23:59:00Z" | grep "opc-next-page" | awk -F":" '{print $2}' | tr -d '"' | tr -d " " | tail -1 ''', shell=True).strip().decode('ascii')
    
            while (PAG != ""):
                p = subprocess.Popen(''' oci logging-search search-logs --search-query 'search "''' + str(COMPARTMENT_ID) + '''/_Audit" | sort by datetime desc' --time-start ''' + str(DATE1) + '''"T00:00:00Z" --time-end ''' + str(DATE1) + '''"T23:59:00Z" --page ''' + str(PAG) + '''  > out.json ''', shell=True, stdout=subprocess.PIPE)
                (output, err) = p.communicate()
                convert_csv()
                PAG = subprocess.check_output(''' oci logging-search search-logs --search-query 'search "''' + str(COMPARTMENT_ID) + '''/_Audit" | sort by datetime desc' --time-start ''' + str(DATE1) + '''"T00:00:00Z" --time-end ''' + str(DATE1) + '''"T23:59:00Z" --page ''' + str(PAG) + ''' | grep "opc-next-page" | awk -F":" '{print $2}' | tr -d '"' | tr -d " " | tail -1 ''', shell=True).strip().decode('ascii')
            print("successfully collected logs for", DATE1)
            DATE1 += timedelta(days=1)
            i = i + 1
    
        print("\nThe .csv file is saved in location /tmp/out.csv")
    
    if __name__ == "__main__":
        myfunc(sys.argv)
    
    

タスク2: カスタムPythonスクリプトの実行

  1. コマンドを使用して、main.pyファイルに実行アクセス権を指定します。

    chmod +x main.py
    
  2. スクリプトは、ログ開始日、ログ終了日およびcompartment-idパラメータを使用して実行する必要があります。スクリプトの正確な使用方法を確認するには、次に示すように'-h'オプションを使用してスクリプトを実行します。

    python3 main.py -h
    

    これにより、スクリプトの正しい構文が表示されます。

    スクリプト・ヘルプ

  3. スクリプトの実行後、スクリプトが実行されている日付が成功メッセージとともに画面に表示され、その後に出力.csvファイルの場所を示すメッセージが表示されます。

    文字

ノート:

nohup python3 main.py -s <log_start_date in YYYY-MM-DD Format> -e <log_end_date in YYYY-MM-DD Format> -c ><Compartment_ID> &

CSVファイルが生成され、/tmp/out.CSVフォルダに格納されます。

タスク3: 監査ログの収集のスケジュール(オプション)

監査ログの月次/週次収集をスケジュールする場合は、cronjobsを設定して、古い.csvファイルを別のファイルにコピーし、新しいログをout.csvファイルに保存します。

  1. 次のコマンドを入力して、crontabを編集します。

    crontab -e
    
  2. 次のcronjobsをスケジュールに追加します。****パラメータをコンパートメント/テナンシのコンパートメントIDに置き換えてください。

    0 1 1 * * export DATE=$(date +'%Y-%m-%d-%T') && cp /tmp/out.csv out-$DATE.csv
    15 1 1 * * export DATE1=$(date +'%Y-%m-%d') && export DATE2=$(date -d "$DATE1 -1 month" +%Y-%m-%d) && python3 main.py -s DATE1 -e DATE2 -c <Compartment_ID>
    

    上記のジョブは毎月1日午前1時および午前1.15時に実行されます。この時間は必要に応じて変更できます。

    ノート: スクリプトで1日遅れやエラーが返されないように、ジョブを月の30日または31日に実行するようにスケジュールできます。

  3. 次のコマンドを使用してファイルを保存し、アクティブなcronjobsを確認します。

    crontab -l
    

謝辞

その他の学習リソース

docs.oracle.com/learnで他のラボをご覧いただくか、Oracle Learning YouTubeチャネルでより無料のラーニング・コンテンツにアクセスしてください。また、education.oracle.com/learning-explorerにアクセスして、Oracle Learning Explorerになります。

製品ドキュメントについては、Oracle Help Centerを参照してください。