Hey,
Thanks for your help. The logic was enough to help me get where I wanted. Below is what I ended up with.
Filtering Linux Auth.log
filter {
if [type] == 'auth' {
grok { match => { 'message' => '%{SYSLOGTIMESTAMP:timestamp} %{HOSTNAME} %{WORD:program}%{GREEDYDATA:msgsplit}' }
}
# SSH successful login
if "grokked" not in [tags] and "sshd" == [program] {
grok { match => [ "msgsplit", "[%{BASE10NUM}]: Accepted password for %{USERNAME:user} from %{IP:src_ip} port %{BASE10NUM}\s+ssh%{BASE10NUM}" ]
add_tag => [ "ssh_successful_login", "grokked" ]
tag_on_failure => [ ]
}
}
# SSH failed login
if "grokked" not in [tags] and "sshd" == [program] {
grok { match => [ "msgsplit", "[%{BASE10NUM}]: Failed password for %{USERNAME:user} from %{IP:src_ip} port %{BASE10NUM}\s+ssh%{BASE10NUM}" ]
add_tag => [ "ssh_failed_login", "grokked" ]
tag_on_failure => [ ]
}
}
# SSH Brute force attemp
if "grokked" not in [tags] and "sshd" == [program] {
grok { match => [ "msgsplit", "[%{BASE10NUM}]: Failed password for invalid user %{USERNAME:user} from %{IP:src_ip} port %{BASE10NUM}\s+ssh%{BASE10NUM}" ]
add_tag => [ "ssh_brute_force", "grokked" ]
tag_on_failure => [ ]
}
}
# Remove excess data
if "grokked" in [tags] and "sshd" == [program]{
mutate {
remove_field => [ "message", "fields", "input_type", "offset", "source", "program", "msgsplit" ]
remove_tag => [ "beats_input_codec_plain_applied" ]
}
}
} #End if[type] == "auth"
} # End Filter