Correlating log messages using pattern databases
The syslog-ng PE application can correlate log messages identified using pattern databases. Alternatively, you can also correlate log messages using the grouping-by() parser. For details, see Correlating messages using the grouping-by() parser.
Log messages are supposed to describe events, but applications often separate information about a single event into different log messages. For example, the Postfix email server logs the sender and recipient addresses into separate log messages, or in case of an unsuccessful login attempt, the OpenSSH server sends a log message about the authentication failure, and the reason of the failure in the next message. Of course, messages that are not so directly related can be correlated as well, for example, login-logout messages, and so on.
To correlate log messages with syslog-ng PE, you can add messages into message-groups called contexts. A context consists of a series of log messages that are related to each other in some way, for example, the log messages of an SSH session can belong to the same context. As new messages come in, they may be added to a context. Also, when an incoming message is identified it can trigger actions to be performed, for example, generate a new message that contains all the important information that was stored previously in the context.
(For details on triggering actions and generating messages, see Triggering actions for identified messages.)
There are two attributes for pattern database rules that determine if a message matching the rule is added to a context: context-scope and context-id. The context-scope attribute acts as an early filter, selecting messages sent by the same process (${HOST}${PROGRAM}${PID} is identical), application (${HOST}${PROGRAM} is identical), or host, while the context-id actually adds the message to the context specified in the id. The context-id can be a simple string, or can contain macros or values extracted from the log messages for further filtering. If a message is added to a context, syslog-ng PE automatically adds the identifier of the context to the .classifier.context_id macro of the message.
NOTE: Message contexts are persistent and are not lost when syslog-ng PE is reloaded (SIGHUP), but are lost when syslog-ng PE is restarted.
Another parameter of a rule is the context-timeout attribute, which determines how long a context is stored, that is, how long syslog-ng PE waits for related messages to arrive.
Note the following points about timeout values:
-
When a new message is added to a context, syslog-ng PE will restart the timeout using the context-timeout set for the new message.
-
When calculating if the timeout has already expired or not, syslog-ng PE uses the timestamps of the incoming messages, not system time elapsed between receiving the two messages (unless the messages do not include a timestamp, or the keep-timestamp(no) option is set). That way syslog-ng PE can be used to process and correlate already existing log messages offline. However, the timestamps of the messages must be in chronological order (that is, a new message cannot be older than the one already processed), and if a message is newer than the current system time (that is, it seems to be coming from the future), syslog-ng PE will replace its timestamp with the current system time.
Example: How syslog-ng PE calculates context-timeout
Consider the following two messages:
<38>1990-01-01T14:45:25 customhostname program6[1234]: program6 testmessage
<38>1990-01-01T14:46:25 customhostname program6[1234]: program6 testmessage
If the context-timeout is 10 seconds and syslog-ng PE receives the messages within 1 sec, the timeout event will occur immediately, because the difference of the two timestamps (60 sec) is larger than the timeout value (10 sec).
-
Avoid using unnecessarily long timeout values on high-traffic systems, as storing the contexts for many messages can require considerable memory. For example, if two related messages usually arrive within seconds, it is not needed to set the timeout to several hours.
Example: Using message correlation
<rule xml:id="..." context-id="ssh-session" context-timeout="86400" context-scope="process">
<patterns>
<pattern>Accepted @ESTRING:usracct.authmethod: @for @ESTRING:usracct.username: @from @ESTRING:usracct.device: @port @ESTRING:: @@ANYSTRING:usracct.service@</pattern>
</patterns>
...
</rule>
For details on configuring message correlation, see the context-id, context-timeout, and context-scope attributes of pattern database rules.
Referencing earlier messages of the context
When using the <value> element in pattern database rules together with message correlation, you can also refer to fields and values of earlier messages of the context by adding the @<distance-of-referenced-message-from-the-current> suffix to the macro. For example, if there are three log messages in a context, and you are creating a generated message for the third log message, the ${HOST}@1 expression refers to the host field of the current (third) message in the context, the ${HOST}@2 expression refers to the host field of the previous (second) message in the context, ${PID}@3 to the PID of the first message, and so on. For example, the following message can be created from SSH login/logout messages (for details on generating new messages, see Triggering actions for identified messages): An SSH session for ${SSH_USERNAME}@1 from ${SSH_CLIENT_ADDRESS}@2 closed. Session lasted from ${DATE}@2 to ${DATE}.
|
Caution:
When referencing an earlier message of the context, always enclose the field name between braces, for example, ${PID}@3. The reference will not work if you omit the braces. |
NOTE: To use a literal @ character in a template, use @@.
Example: Referencing values from an earlier message
The following action can be used to log the length of an SSH session (the time difference between a login and a logout message in the context):
<actions>
<action>
<message>
<values>
<value name="MESSAGE">An SSH session for ${SSH_USERNAME}@1 from ${SSH_CLIENT_ADDRESS}@2 closed. Session lasted from ${DATE}@2 to ${DATE} </value>
</values>
</message>
</action>
</actions>
If you do not know in which message of the context contains the information you need, you can use the grep template function. For details, see grep.
Example: Using the grep template function
The following example selects the message of the context that has a username name-value pair with the root value, and returns the value of the auth_method name-value pair.
$(grep ("${username}" == "root") ${auth_method})
To perform calculations on fields that have numerical values, see Numerical operations.
Triggering actions for identified messages
The syslog-ng PE application can generate (trigger) messages automatically if certain events occur, for example, a specific log message is received, or the correlation timeout of a message expires. Basically, you can define messages for every pattern database rule that are emitted when a message matching the rule is received. Triggering messages is often used together with message correlation, but can also be used separately. When used together with message correlation, you can also create a new correlation context when a new message is received.
The generated message is injected into the same place where the db-parser() statement is referenced in the log path. To post the generated message into the internal() source instead, use the inject-mode() option in the definition of the parser.
Example: Sending triggered messages to the internal() source
To send the generated messages to the internal source, use the inject-mode(internal) option:
parser p_db {db-parser(
file("mypatterndbfile.xml")
inject-mode(internal)
);};
To inject the generated messages where the pattern database is referenced, use the inject-mode(pass-through) option:
parser p_db {db-parser(
file("mypatterndbfile.xml")
inject-mode(pass-through)
);};
The generated message must be configured in the pattern database rule. It is possible to create an entire message, use macros and values extracted from the original message with pattern database, and so on.
Example: Generating messages for pattern database matches
When inserted in a pattern database rule, the following example generates a message when a message matching the rule is received.
<actions>
<action>
<message>
<values>
<value name="MESSAGE">A log message from ${HOST} matched rule number $.classifier.rule_id</value>
</values>
</message>
</action>
</actions>
To inherit the properties and values of the triggering message, set the inherit-properties attribute of the <message> element to TRUE. That way the triggering log message is cloned, including name-value pairs and tags. If you set any values for the message in the <action> element, they will override the values of the original message.
Example: Generating messages with inherited values
The following action generates a message that is identical to the original message, but its $PROGRAM field is set to overriding-original-program-name
<actions>
<action>
<message inherit-properties='TRUE'>
<values>
<value name="PROGRAM">overriding-original-program-name</value>
</values>
</message>
</action>
</actions>
Example: Creating a new context from an action
In syslog-ng PE version 7 and newer, you can create a new context as an action. For details, see Element: create-context.
The following example creates a new context whenever the rule matches. The new context receives 1000 as ID, and program as scope, and the content set in the <message> element of the <create-context> element.
<rule provider='test' id='12' class='violation'>
<patterns>
<pattern>simple-message-with-action-to-create-context</pattern>
</patterns>
<actions>
<action trigger='match'>
<create-context context-id='1000' context-timeout='60' context-scope='program'>
<message inherit-properties='context'>
<values>
<value name='MESSAGE'>context message</value>
</values>
</message>
</create-context>
</action>
</actions>
</rule>
For details on configuring actions, see the description of the pattern database format.
Conditional actions
To limit when a message is triggered, use the condition attribute and specify a filter expression: the action will be executed only if the condition is met. For example, the following action is executed only if the message was sent by the host called myhost.
<action condition="'${HOST}' == 'myhost'">
You can use the same operators in the condition that can be used in filters. For details, see Comparing macro values in filters.
The following action can be used to log the length of an SSH session (the time difference between a login and a logout message in the context):
<actions>
<action>
<message>
<values>
<value name="MESSAGE">An SSH session for ${SSH_USERNAME}@1 from ${SSH_CLIENT_ADDRESS}@2 closed. Session lasted from ${DATE}@2 ${DATE} </value>
</values>
</message>
</action>
</actions>
Example: Actions based on the number of messages
The following example triggers different actions based on the number of messages in the context. This way you can check if the context contains enough messages for the event to be complete, and execute a different action if it does not.
<actions>
<action condition='"$(context-length)" >= "4"'>
<message>
<values>
<value name="PROGRAM">event</value>
<value name="MESSAGE">Event complete</value>
</values>
</message>
</action>
<action condition='"$(context-length)" < "4"'>
<message>
<values>
<value name="PROGRAM">error</value>
<value name="MESSAGE">Error detected</value>
</values>
</message>
</action>
</actions>