You are here : Home » Learning security » Operating Systems » GNU Linux » Real-time system alerts using Twitter OAuth (implementation)

Real-time system alerts using Twitter OAuth (implementation)

D 6 June 2010     H 03:09     A Emeric Nasi     C 2 messages


agrandir

Note: In order to understand this document it is strongly recommended you already read the theory article.
Also the author suppose the reader have a good base about GNU Linux and security.
English is not my first language, do not hesitate to point our any "bad writing".
License : Copyright Emeric Nasi, some rights reserved
This work is licensed under a Creative Commons Attribution 4.0 International License.
Creative Commons License

Introduction

I really like Twitter. I opened my own account a few days ago.
I was looking at the Twitter features. I just tough that Twitter could be used for more than public communications.
A problem you may face when dealing with monitoring is the reaction time. And having real-time alerts is the big issue.
I found out Twitter’s API could be used for that, in a more secure way then classic emails.
I implemented this solution and I will present it to you using two articles.
This is the second article, in which we are now going to implement the solution we discussed in the first one.

Warning : You should really read the "Theory" article and learn about OAuth before you try to implement the solution proposed in this article.

I Choose the tools

So what do we need?

  • An entity that watches logs and that has real-time actions enabled.
  • An entity that can use the Twitter over OAuth

I.1 Swatch for the real-time alert

I choose swatch because it is simple to understand and it is enough for what we are going to do.
The basic Swatch functioning is simple. It watches a file for any new added text. If the new text contains a certain string or pattern,
it will action an alert mechanism. This alert can be an echo, sending a mail, executing another program, etc.
Install swatch :
apt-get install swatch # for Debian based distrib
yum install swatch # for RedHat based distrib

I.2 Perl for the OAuth/Twitter API

Among the possible languages, I choose perl because it is fast and easy to write a program that does just what we need with it.
Perl has also a Twitter module that is well documented and easy to use.

Note : I am not especially a Perl fan but the Twitter module really convinced me.

First install perl if it isn’t already installed on your system (that is quite unprobable).
apt-get install perl # for Debian based distrib
yum install perl # for RedHat based distrib
After that install the OAuth CPAN perl module.
perl -MCPAN -e "install Net::OAuth"
When you have done that, you can implement OAuth calls and write your own
Twitter over OAuth code.
However why reinvent the wheel when a nice Twitter over OAuth module already exists?
Install this module :
perl -MCPAN -e "install Net::Twitter"

Note : The previous command might ask you to install a lot of dependencies, you should be alright by sticking to default proposals.

II Configure the tools

Note : Most of the below code comes from my application Thylacine (not yet released).

II.1 Create a special monitoring group.

groupadd -f --system thyl_g_monitor

II.2 Create the system directories.

  1. MONITOR_PATH="/etc/sevagas/monitor" # Our application path
  2. (umask 026 && mkdir -p "$MONITOR_PATH") # Create path
  3. chown root:thyl_g_monitor "$MONITOR_PATH" # Change group ownership
  4. chmod 2750 "$MONITOR_PATH" # Setgid bit and prevent "Others" access
  5. mkdir "$MONITOR_PATH/tmp" # Create temporary folder
  6. chmod 3770 "$MONITOR_PATH/tmp" # Members of monitor group can add files but only owner of files can delete them
  7. mkdir "$MONITOR_PATH/twitter"
  8. chmod 750 "$MONITOR_PATH/twitter"

II.3 Create perl script.

Perl’s Net::Twitter module allows easy access and manipulation of the Twitter API, includind OAuth authentication.
In our case, after authentication, we are going to use the private message (direct message) call.
What is great about private message is that if you have activated the mobile features, you will also receive the alert by sms.
This script must be called with one parameter (the system alert)
and will send our system alert via private messages to our own Twitter account.

Create the file :
touch /etc/sevagas/monitor/twitter/the_bird_sentinel.pl
chmod 750 /etc/sevagas/monitor/twitter/the_bird_sentinel.pl
Now open it with your favorite text editor and paste the next code

  1. #!/usr/bin/perl
  2. # Adapted from http://search.cpan.org/~mmims/Net-Twitter-3.13003/lib/Net/Twitter/Role/OAuth.pm
  3. use Net::Twitter;
  4.  
  5. # Save access token function
  6. sub save_access_tokens # if necessary
  7. {
  8. my ($at,$ats) = @_;
  9. # Grab keys
  10. $file = '/etc/sevagas/monitor/twitter/access-token';
  11. open(INFO, ">$file") or die("open: $!"); # open in write-only mode
  12. print INFO "$at"; # Save access token
  13. close(INFO);
  14. $file = '/etc/sevagas/monitor/twitter/access-token-secret';
  15. open(INFO, ">$file"); # open in write-only mode
  16. print INFO "$ats"; # Save accecc token secret
  17. close(INFO);
  18. return 0;
  19. }
  20. # Restore access token function
  21. sub restore_access_tokens
  22. {
  23. # Grab keys
  24. $file = '/etc/sevagas/monitor/twitter/access-token';
  25. open(INFO, "<$file") or return 0; # open in read-only mode
  26. $at = <INFO>;
  27. chomp $at; # remove '\n' at end of line
  28. close(INFO);
  29. $file = '/etc/sevagas/monitor/twitter/access-token-secret';
  30. open(INFO, "<$file") or return 0; # open in read-only mode
  31. $ats = <INFO>;
  32. chomp $ats; # remove '\n' at end of line
  33. close(INFO);
  34. return ($at,$ats);
  35. }
  36.  
  37. # get first arg (direct message)
  38. $direct_message = $ARGV[0];
  39. if ( ! $direct_message ){
  40. print "This script requires one argument (the private message you wish to send).\n";
  41. exit(1);
  42. }
  43. # Grab consumer keys
  44. $file = '/etc/sevagas/monitor/twitter/consumer-key';
  45. open(INFO, "<$file") or die("open: $!"); # open in read-only mode
  46. $consumerKey = <INFO>;
  47. chomp $consumerKey; # remove '\n' at end of line
  48. close(INFO);
  49. $file = '/etc/sevagas/monitor/twitter/consumer-secret';
  50. open(INFO, "<$file") or die("open: $!"); # open in read-only mode
  51. $consumerSecret = <INFO>;
  52. chomp $consumerSecret; # remove '\n' at end of line
  53. close(INFO);
  54. #print "Consumer key : $consumerKey\n";
  55. #print "Consumer secret : $consumerSecret\n";
  56.  
  57. my $nt = Net::Twitter->new(
  58. traits => ['API::REST', 'OAuth'],
  59. consumer_key => $consumerKey,
  60. consumer_secret => $consumerSecret,
  61. );
  62.  
  63. my($access_token, $access_token_secret) = restore_access_tokens();
  64.  
  65. if ($access_token && $access_token_secret) {
  66. #print "Access token : $access_token \n";
  67. #print "Acces token secret : $access_token_secret \n";
  68. $nt->access_token($access_token);
  69. $nt->access_token_secret($access_token_secret);
  70. }
  71.  
  72. unless ( $nt->authorized ) {
  73. # The nt is not yet authorized: Do it now
  74. print "Authorize this app at ", $nt->get_authorization_url, " and enter the PIN#\n";
  75.  
  76. my $pin = <STDIN>; # wait for input
  77. chomp $pin;
  78.  
  79. my($access_token, $access_token_secret, $user_id, $screen_name) = $nt->request_access_token(verifier => $pin);
  80. save_access_tokens($access_token, $access_token_secret); # if necessary
  81. }
  82.  
  83. # Everything's ready!
  84. # Send a direct message to myself
  85. $nt->new_direct_message("< your Twitter account >", $direct_message );
  86.  
  87. exit(0);
Note : Replace the text "< your Twitter account >" by your Twitter account (at the end of the file).

II.4 Follow Twitter OAuth workflow

Open your favorite navigator and log into your Twitter account.
Register for OAuth applications at http://twitter.com/oauth_clients
Correctly fill in the form. We assume the application name is The bird sentinel.
Choose "Client" application type, choose "Read and write" default access type and check "Yes, use Twitter for login". Then validate the form.
>> You should see a "Success" message.
The page your are on now is very important, you should note down all informations.
Type the following instructions :

  1. touch "$MONITOR_PATH/twitter/consumer-key"
  2. chmod 640 "$MONITOR_PATH/twitter/consumer-key"
  3. echo "< your consumer key >" > "$MONITOR_PATH/twitter/consumer-key"
  4. touch "$MONITOR_PATH/twitter/consumer-secret"
  5. chmod 640 "$MONITOR_PATH/twitter/consumer-secret"
  6. echo "< your consumer secret >" > "$MONITOR_PATH/twitter/consumer-secret"

After that, launch our perl script manually for initial authentication.
Be sure you are still logged into your Twitter account.
/etc/sevagas/monitor/twitter/the_bird_sentinel.pl "Hello!"
The script should suggest you to authorize the application at a given twitter address and enter a pin code.
Open your navigator at that address and accept to authorize the bird sentinel application.
>> You’ve successfully granted access to the bird sentinel!
Type the pin code in the script console and press enter.
OK you are now authorized to use the twitter API !!!
To verify that it worked, go to your Twitter account, you should have received a new private message :-).
You should also observe that the access token files are created in /etc/sevagas/monitor/twitter/

II.5 Configure swatch.

Swatch real-time alert is nice but the default installation has some lacks we are going to correct.
First we are going to run swatch daemon as its own system user.
useradd --system --no-user-group --gid thyl_g_monitor --groups adm  -s /bin/false  --comment "Swatch System User" thyl_u_swatch

Note : We added the swatch user to the group ’adm’ to allow it to read system logs (/var/log/message for example)

Now swatch will run as ’thyl_u_swatch’ and will be able to read any files whose group is ’thyl_g_monitor’ or ’adm’.

Swatch generates some temporary files we want to clean.
We are going to write a cron job for that :

  1. (umask 027 && touch /etc/cron.weekly/clean-swatch)
  2. echo '#!/bin/sh' > /etc/cron.weekly/clean-swatch
  3. echo "# This script removes old tmp files generated by swatch in /etc/sevagas/monitor/tmp" >> /etc/cron.weekly/clean-swatch
  4. echo "find /etc/sevagas/monitor/tmp -name \"*swatch*\" -type f -atime +3 -delete" >> /etc/cron.weekly/clean-swatch
  5. echo >> /etc/cron.weekly/clean-swatch
  6. chmod 700 /etc/cron.weekly/clean-swatch

Now we are ready to configure our swatch for twitter daemon!
We can do much more but for our example we are going to watch the file /var/log/messages for any new message containing the word "bird_alert".
We create the swatch configuration file :
(umask 037 &&  touch "/etc/sevagas/monitor/swatch-twitter.conf")
Now edit the file /etc/sevagas/monitor/swatch-twitter.conf :

  1. watchfor /bird_alert/
  2. exec /etc/sevagas/monitor/twitter/the_bird_sentinel.pl "$_"
  3. threshold type=limit,count=1,seconds=30

Now create the init script to launch our daemon:
(umask 077 && touch /etc/init.d/swatch-twitter)  
Edit /etc/init.d/swatch-twitter and add next code :

  1. #!/bin/bash
  2. ### BEGIN INIT INFO
  3. # Provides: swatch for twitter daemon
  4. # Required-Start:
  5. # Required-Stop:
  6. # Default-Start: 2 3 4 5
  7. # Default-Stop: 0 6
  8. # Short-Description: Launches swatch daemon for twitter real-time alert
  9. # Description:
  10. ### END INIT INFO
  11.  
  12. # Author: Emeric Nasi
  13. # Contact : emeric.nasi[at]sevagas.com
  14.  
  15. displayHelp () {
  16. echo " Swatch for twitter , usage : /etc/init.d/swatch-twitter start|stop|status "
  17. echo " All config and tmp file are stored in /etc/sevagas/thylacine/monitor/"
  18. exit 3
  19. }
  20.  
  21. if [ $# != 1 ]
  22. then
  23. displayHelp
  24. fi
  25. case "$1" in
  26. start)
  27. echo "Starting swatch for twitter..."
  28. startCommand="swatch --daemon --pid-file /etc/sevagas/monitor/tmp/swatch-twitter.pid --script-dir=/etc/sevagas/monitor/tmp -c /etc/sevagas/monitor/swatch-twitter.conf -t /var/log/messages"
  29. if which sudo &>/dev/null # We run swatch with its own user (with sudo or su)
  30. then
  31. sudo -u thyl_u_swatch $startCommand
  32. else
  33. su -c "$startCommand" thyl_u_swatch
  34. fi
  35. ;;
  36. stop)
  37. echo "Stopping swatch for twitter..."
  38. kill $( cat "/etc/sevagas/monitor/tmp/swatch-twitter.pid" )
  39. rm /etc/sevagas/monitor/tmp/swatch-twitter.pid
  40. ;;
  41. status)
  42. if [ -f /etc/sevagas/monitor/tmp/swatch-twitter.pid ]
  43. then
  44. echo "swatch for twitter is running, process $(cat "/etc/sevagas/monitor/tmp/swatch-twitter.pid")."
  45. else
  46. echo "swatch for twitter is not running."
  47. fi
  48. ;;
  49. *)
  50. displayHelp
  51. esac
  52. exit 0

Make script executable :
chmod 700 /etc/init.d/swatch-twitter
Install rc.d :
update-rc.d  swatch-twitter defaults # Starts at runlevel 2,3,4,5

III Test and Adapt

III.1 A quick test!

Run the swatch daemon :
/etc/init.d/swatch-twitter start
>>You should have the tmp files in etc/sevagas/monitor/tmp/
Now lets test our system!
echo "bird_alert : this is an alert" >> /var/log/messages
You can log into your twitter account and check your private messages, you should find a nice message containing "bird_alert : this is an alert" !!!

Pfiew, we are arriving at the end of this article. You can now modify the previous scripts
to adapt them at your own needs! You can combine this system with an IDS a firewall or any other soft that writes logs.

However, before doing anything read the next section...

III.2 Caution!

Be careful not to spam or flood Twitter with your logs!
You should only send the really bad alert and do not send the same alert again and again
Maybe you should keep the "bird_watcher" string required so you are sure other logs wont flood your twitter account.
Just be sure critical logging has the string "bird_watcher" inside the log.
Another thing, twitter has maximum 140 characters messages, if you want to send bigger messages, implement a system that truncates big messages in smaller ones.
Finally remember that Twitter has implemented the next limits :

  • Direct Messages: 250 per day
  • API Requests: 150 per hour
  • Updates: 1000 per day
Note : Because direct messages are limited, alternative to the previous perl script would be to use status updates instead of direct messages. You can configure your account so that your status updates are private.

However, I hope that you won’t need more than 250 messages a day... 250 different critical alerts in one day means you don’t sleep to much...
And you should do a general security review of your systems!
Read more about Twitter imposed limits at http://help.twitter.com/forums/10711/entries/15364

1 Forum posts

Any message or comments?
pre-moderation

This forum is moderated before publication: your contribution will only appear after being validated by an administrator.

Who are you?
Your post