Humans have an innate need to communicate. Most people want to talk to other people. Data geeks want to talk to data and hope at some point it starts talking back. Logstash can’t make your data talk (yet!), but it can at least make your server talk back to you. Here’s how:

The concept is simple. Using XMPP, a simple chat / distributed message protocol, as both an input and output for logstash, we can send and receive messages. A creative ruby filter in the middle lets the magic happen. I’ve skipped over setting up an XMPP server and all the accounts and stuff. If you need assistance, say so in the comments and I’ll make an effort to write that up.

Firstly, the XMPP setup. This took some tweaking before it worked. Mostly due to my ignorance of XMPP concepts, partly due to the lack of complete documentation of the XMPP input / output. This Logstash config sets up logstash to listen in a room for any messages directed to it. On receipt of a message it will send the message back to the room:

input {
  xmpp {
    user => "[email protected]/Listener"
    host => "eagerelk.com"
    password => "password"
    rooms => "[email protected]/Listener"
  }
}

filter {
  if [from] == "admin" {
    mutate { add_tag => "can_reply" }
  } 
}

output {
  stdout {
    codec => rubydebug
  }
  
  if "can_reply" in [tags] {
    xmpp {
      user => "[email protected]/Talker"
      host => "eagerelk.com"
      password => "password"
      rooms => "[email protected]/Talker"
      message => "You said %{message}"
    }
  }
}

That should sign in logstash as both a normal user as well as a participant to the letstalk room on the eagerelk.com XMPP server. Notice the different Resource Identifiers for the input and output, as well as the fact that the Resource Identifiers are the same for the user and the rooms. Since we’re effectively signing up from two locations (input and output) the Resource ID’s need to differ. The filter is there so that we don’t echo back our own messages. I must admit that I find it quite easy (and funny!) to create endless loops with logstash… Anyhoo, here’s logstash being childish and repeating everything I say:

HelloWorld

Not everything that comes in from the specified user is a command, so this requires the command to be preceded by do. We use the grok filter to check that and capture the command:

  # This is added to the filter block
  grok {
    match => [ "message", "do (?<command>.*)" ]
    add_tag => [ "can_execute" ]
  }

We’ve determined that we have received a command and what the command is. Now we need to execute it. We use the ruby filter to execute the command. Notice that we’re using the can_execute tag to identify the event as a legitimate command:

  # This is added to the filter block
  if "can_execute" in [tags] {
    if [command] in [ "free", "df" ] {
      ruby {
        code => "event['result'] = `#{event['command']}`"
        add_tag => [ "executed" ]
      }
    } else {
      mutate {
        add_tag => [ "blacklisted_command" ]
      }
    }
  }

Notice again the use of tasks to identify the event as a successful command or a blacklisted one. Now you can ask logstash to execute certain commands on your server. Nifty!

Executed

I find that this goes without saying, but you never know. Do NOT allow the execution of any command through this. It’s a huge security risk. Rather whitelist the commands (as we’ve done here) and don’t trust anything that comes from the user.

The full config file is below for reference:

input {
  xmpp {
    user => "[email protected]/Listener"
    host => "eagerelk.com"
    password => "password"
    rooms => "[email protected]/Listener"
  }
}

filter {
  if [from] == "admin" {
    mutate {
      add_tag => [ "can_reply" ]
    }

    grok {
      match => [ "message", "do (?<command>.*)" ]
      add_tag => [ "can_execute" ]
    }
  }

  if "can_execute" in [tags] {
    if [command] in [ "free", "df" ] {
      ruby {
        code => "event['result'] = `#{event['command']}`"
        add_tag => [ "executed" ]
      }
    } else {
      mutate {
        add_tag => [ "blacklisted_command" ]
      }
    }
  }
}

output {
  stdout {
    codec => rubydebug
  }

  if "executed" in [tags] {
    xmpp {
      user => "[email protected]/Talker"
      host => "eagerelk.com"
      password => "password"
      rooms => "[email protected]/Talker"
      message => "Result: %{result}"
    }
  }
}

Coder. Thinker. Human. I try to write good code for a living and wrangle data as a hobby. Be sure to check out the book I'm writing: The Logstash Config Guide.

Subscribe To Our Newsletter

Subscribe To Our Newsletter

Join our mailing list to receive the latest news and updates from our team.

You have Successfully Subscribed!

Share This