Monitoring a local file using OSSEC Integration

From khika
Revision as of 07:21, 4 June 2019 by Rajesh kulkarni (talk | contribs) (Parse the file using extensible KHIKA Adapter for OSSEC)
Jump to navigation Jump to search

In addition to event logs or syslogs, a lot of local files are created by various applications. These files reside on the hosts/servers where applications run and contain wealth of information, valuable for both security and operational intelligence. The application logs are useful for debugging or capturing run time errors/exception or even business opportunities in production production environments. It is imperative to monitor local files for gaining actionable insights, real time alerting, correlations and forensic debugging.

KHIKA integrates closely with OSSEC to monitor application logs in real time. This section explains how to use OSSEC to monitor the application logs. We begin with broad level steps and then dive deep into each step so that we explain the methodology and the intricate details associated with it. At a broad level you perform following steps

Install an OSSEC Agent on the end node.

OSSEC Agent provides the simplest way to monitor a local file on any computer in real time. You must install the OSSEC agent where the file is being created. Please refer the appropriate section sections on Linux or Windows for installing the OSSEC Agent.

Configure the OSSEC Agent to monitor the local file

Once the OSSEC agent is installed, you need to locate the file you want to monitor. In this example, we will monitor apache access logs created in the directory /path/of/apache/access/log and name of the file is access.log

  1. Login to OSSEC Agent node and open file ossec.conf. On Windows this file is located in C:\Program Files (x86)\ossec-agent directory . On Linux, you will find it at /vat/ossec/ossec-agent/etc directory. (if you have installed the agent in the default location)
  2. Locate section <localfile>. Note that ossec.conf uses XML formatting and hence you have to be careful enough not to disturb the other tags. Navigate just above "Rootcheck - Policy monitor config" tag and insert following section
 <localfile>
   <location>/path/of/apache/access/log/access.log</location>
   <log_format>syslog</log_format>
 </localfile>

Note that we have added <log_format>syslog<log_format> as the apache access logs are single line messages and OSSEC will treat them same as syslog messages.

We save the file and restart OSSEC Agent. This will start apache access logs being received on the OSSEC Server side (i.e. on Data Aggregator Node).

Login to KHIKA Data Aggregator and navigate to directory /opt/ossec/logs/archives/2019/May/ (needless to say, enter current year and month). Here you will find a multiple directories with names of workspaces prepended to it. Enter appropriate directory and check the current file. You should see live logs coming from our newly added apache server

Parse the file using extensible KHIKA Adapter for OSSEC

As OSSEC Server on your KHIKA Data Aggregator starts receiving live logs, you will observe that all the logs are being gathered in the same file. If you have already configured OSSEC Adapter via KHIHKA App for Linux or KHIKA App for Windows, you will need to tell this Adapter to parse the Apache access logs using the appropriate parser logic. This is where extensible KHIKA Adapter for OSSEC comes handy.

KHIKA Adapter for OSSEC is modular and can be extended by adding an appropriate python to it. To understand how to add a new python a function to parse a new type of logs, let us first understand the structure of this adapter.

  1. Login to KHIKA Data Aggregator and go to directory /opt/KHIKA/Apps/Adapters/OssecArchiveLog
  2. You will find a file filename_parser_mapping.csv. Open this file and check the header and a couple of first lines
  Parser_ID,File_Name,Parser_Name,Invoke_Parser,Headers,"Agent Source Name"
  1,"(\/var\/log\/audit\/audit.log)","unix_audit","CallProcessUnixAuditLogLine",,
  2,"(\/project\/job\/remove_NetScreen_)(.*)(log)","juniper_netscreen","CallProcessJuniperNetscreenLogLine",,
  3,"(\/project\/job\/remove_fortigate.log)","varnish_apache_access_logs","CallProcessVarnishApacheAccessLogLine",,

Parser_ID = The sequence number of the parser. This is nothing but a unique number File_Name = This is path of the regular expression to the path of the file on agent. Note the escape sequence in the name of the file Parser_Name = The name of parser (python function to be involved when a line from File_Name if encountered in he OSSEC Archive log Invoke_Parser = Is string identifier of Parser_Name.

We will talk more about these fields with example as we move ahead and explore the code.

  1. As we want to monitor "/path/of/apache/access/log/access.log" we will add a new line to filename_parser_mapping.csv at the end and increment the sequence number. Lets say I add the new line as 4th record, our file filename_parser_mapping.csv should look like this
  Parser_ID,File_Name,Parser_Name,Invoke_Parser,Headers,"Agent Source Name"
  1,"(\/var\/log\/audit\/audit.log)","unix_audit","CallProcessUnixAuditLogLine",,
  2,"(\/project\/job\/remove_NetScreen_)(.*)(log)","juniper_netscreen","CallProcessJuniperNetscreenLogLine",,
  3,"(\/project\/job\/remove_fortigate.log)","varnish_apache_access_logs","CallProcessVarnishApacheAccessLogLine",,
  4,"(\/path\/of\/apache\/access\/log\/access.log)","varnish_apache_access_logs","CallProcessVarnishApacheAccessLogLine",,

We use varnish_apache_access_logs as the Parser_name and CallProcessVarnishApacheAccessLogLine as the string identifier for the same. This is existing Apache Access log parser shipped with KHIKA and we will use for the demonstration purpose.

Basically, by adding the above line in filename_parser_mapping.csv file we instructed the OSSEC parser to invoke function varnish_apache_access_logs() when a log message from /path/of/apache/access/log/access.log.

Lets walk through some python code and understand how we achieve this.

Open TLHookScript_ArchivesMasterParser.py and search for CallProcessVarnishApacheAccessLogLine

                elif (re_file_parser_dict[parser_id][2] == "CallProcessVarnishApacheAccessLogLine"):
                    if g_normalized_apache == 0:
                        if platform.system() == 'Windows':
                            NORMALIZER_DIR = site.getsitepackages()[0] + '/share/logsparser/normalizers'
                        else:
                            NORMALIZER_DIR = os.path.dirname(os.path.realpath(__file__)) + '/../../../3rdpartyUnix/TLPython/share/logsparser/normalizers'
                        apache_normalizer = LN(NORMALIZER_DIR)
                        apache_normalizer.set_active_normalizers({"apache-0.99" : True})
                        apache_normalizer.activate_normalizers()

                    parsed_output = invoke_parser(g_process_line,g_file,line_count,g_hostname,logger, apache_normalizer,GetTimeStampWithFormat) 

invoke_parser() is a function pointer which actually calls CallProcessVarnishApacheAccessLogLine() with arguments such as g_process_line,g_file,line_count,g_hostname,logger, apache_normalizer,GetTimeStampWithFormat

So, the real call is CallProcessVarnishApacheAccessLogLine(). You can pass any arguments to it but first few are highly recommended (though not compulsory as you are free implement it the way you want) 1)g_process_line is the line to be processed 2)g_file name is of file (on agent) 3)line_count represents line count 4)g_hostname is basically the name of the aggregator 5)logger is our logger object Other arguments can be specific to your logic. As in this case we are passing apache_normalizer object created just above and some other stuff.

Essentially, if you are extending OSSEC Parser, you can copy paste above block of code and replace "CallProcessVarnishApacheAccessLogLine" with your own function.

Now let us inspect the code of CallProcessVarnishApacheAccessLogLine() function. Open file TLHookLibrary_parsers.py and go to "def CallProcessVarnishApacheAccesLogLine".

  def CallProcessVarnishApacheAccessLogLine(line,file,line_count,g_hostname,logger, normalizer,dict_device_timezone):
      from CommonLibrary import TLHookScript_apache_varnish_access as TLVARNISH
      return TLVARNISH.ProcessLineOfFile(line,file,line_count,g_hostname,logger,normalizer,dict_device_timezone)

Set enrichment rules (if any)

Set the index in Elastic Search

Define alerts and dashboards

Define alerts and correlations