Tuesday, September 30, 2014

How to get Ubuntu 14.04 security update notifications sent to your inbox using Gmail.

We can set up a cron job to email security updates using Gmail over SSMTP (yes, the same app we used before to send email notifications for someone pressing the doorbell in a previous project). SSMTP, not to be confused with SMTP, is easy enough to use and set up, but it's not the most secure as your password is in plain text. I recommend signing up for and using a throwaway/junk Gmail account for this.

Prerequisites:

  • Ubuntu 14.04 LTS Server
  • A spare gmail account that you don't care about



SU into root and install ssmtp:

sudo su - 
apt-get install ssmtp

Move the default config to a backup:

mv /etc/ssmtp/ssmtp.conf /etc/ssmtp/ssmtp.bkp

We are going to create a new conf file in its place:

vi /etc/ssmtp/ssmtp.conf

(for new vi users press "i" here to enter insert mode... or just use nano or whatever you prefer)

# The user that gets all the mails (UID < 1000, usually the admin)
root=youremail@gmail.com

# The mail server (where the mail is sent to), both port 465 or 587 should be acceptable
# See also http://mail.google.com/support/bin/answer.py?answer=78799
mailhub=smtp.gmail.com:587

# The address where the mail appears to come from for user authentication.
rewriteDomain=gmail.com

# The full hostname
hostname=yourhostname

# Use SSL/TLS before starting negotiation
UseTLS=Yes
UseSTARTTLS=Yes

# Username/Password
AuthUser=youremail@gmail.com
AuthPass=yourpassword

# Email 'From header's can override the default domain?
FromLineOverride=yes

(again, for new vi users save the file by pressing Escape and typing :wq)

Update the security for your conf file since your password is in plain text:
chmod 640 /etc/ssmtp/ssmtp.conf

cd back to root:
cd /root
(or just simply type cd to get home)

Verify your SSMTP is working and has proper permissions:

echo "Hello world" >  test.txt
cat test.txt | ssmtp myemail@gmail.com



Once you receive an email (make sure to check the sent folder on the sending side and the spam folder on the receiving end) now we can check for security updates using my previous post:

/usr/lib/update-notifier/apt-check --human-readable

To break this down, look at what it's doing. /usr/lib/update-notifier/apt-check by itself returns a very unhelpful 0;0. The --human-readable directive adds some verbosity:

0 packages can be updated.
0 updates are security updates.

...but we don't want an email for every chrome/firefox/general bug update. We want to focus in on the security patches. To do this, we can use grep to give us just the security update totals. The script so far is, check for updates, make it easy to read, pipe it to "grep" with a "-i" (case insensitive) with the term "security".

/usr/lib/update-notifier/apt-check --human-readable | grep -i security

and the output

0 updates are security updates.

While the output is better, now we see  0 updates are security updates, we can distill it even further with awk.

/usr/lib/update-notifier/apt-check --human-readable | grep -i security  | awk '{ print $1 }'

So, that line is reduced to the first set of numbers. Literally the number itself

0

We are passing the argument to awk, $1, which means the first set of numbers in that row. We can now put together a very simple and crude cron job (there are many ways to skin a cat, this is for demonstrative purposes... also because I'm not the worlds best scripter)




Let's start off by creating the script.

vi patch_notify.sh

Now, we can paste in the following:

#!/bin/bash
CURDATE=`date`
TTIME=`date +"%r"`

SECUPD=$( /usr/lib/update-notifier/apt-check --human-readable | grep -i security  | awk '{ print $1 }' )


if [ $SECUPD -eq "0" ]
then
       echo "There are $SECUPD updates."

else

       if [ $SECUPD -eq "1" ]
       then

       ssmtp your-send-to-email@gmail.com <<-EOF
       From: username <youremail@gmail.com>
       To: your-send-to-email@gmail.com
       Subject: Weekly security updates - $CURDATE

       $SECUPD security update is waiting for your installation as of $TTIME.

       EOF

       else

               if [ $SECUPD -gt "1" ]
               then

               ssmtp your-send-to-email@gmail.com <<-EOF
               From: username <youremail@gmail.com>
               To: your-send-to-email@gmail.com
               Subject: Weekly security updates - $CURDATE

               $SECUPD security updates are waiting for your installation as of $TTIME.

               EOF
               fi
       fi
fi


To break this script down, ultimately it's in 3 parts. Is the patch total 0? No emails. Is the patch level 1, yes, email (but with proper syntax; singular vs plural, because I'm anal like that). Is there more than one patch? Yes, send an email.

To get into the guts of it

We are telling it to use (the recently very infamous) bash shell.
#!/bin/bash
Now we are setting the variables for the date and time
CURDATE=`date`
TTIME=`date +"%r"`
You can run date in the command line and see what's copied into the variable, now CURDATE. Also date +"%r" which shows just time time 06:58:46 PM, that is copied as TTIME.

We are also setting the SECUPD variable. This takes the output from awk output and associates itself with SECUPD.

SECUPD=$( /usr/lib/update-notifier/apt-check --human-readable | grep -i security  | awk '{ print $1 }' ) The only difference is the formatting around the command.

The -eq command operator is "equal". So we are saying if the value of $SECUPD is exactly 0,

if [ $SECUPD -eq "0" ]
echo "There are $SECUPD updates."

We display "There are 0 updates." and an email is not generated.


If there is 1 security update for us:

if [ $SECUPD -eq "1" ]

We send an email to our main email address. The subject will show "Weekly security updates" and the current date. The body will show

$SECUPD security update is waiting for your installation as of $TTIME.
or
1 security update is waiting for your installation as of 07:01:32 PM.

The EOF's encapsulate what will be sent to SSMTP


If there is more than one update available:

if [ $SECUPD -gt "1" ]
If the updates are greater than one, (not greater or equal, but literally 2+) then we send this:

$SECUPD security updates are waiting for your installation as of $TTIME.
or
12 security updates are waiting for your installation as of 07:03:13 PM.

We now need to make our script executable

chmod +x patch_notify.sh

You should just be able to run

./patch_notify.sh

If you have no critical patches, you should see:

There are 0 updates.



This script is butchered pretty bad, but it's a good beginner script. You can change the context, remove the dates, the layout, the wording. You can also simplify it to send you an email only if it's above a dozen updates. Or even send you an email, regardless of how many security patches, even 0, at a set interval with cron.

So, now to automate the script (this was written for Debian based systems, specifically Ubuntu 14.04 LTS Server... but should be pretty close to the same across all platforms)

We are going to do a weekly scan, on a Saturday at noon.

Edit the crontab:

crontab -e

To edit the cron job (also crontab -l to list jobs you already have)

0 12 * * 6 /root/patch_notify.sh

This tells the cron daemon to run your script in its relative path /root/ every Saturday at noon.

Feel free to bug me and ask questions (or correct me... I know I probably screwed up somewhere... but it's working for me so far)

Check how many security updates are available on Ubuntu 14.04 LTS

/usr/lib/update-notifier/apt-check --human-readable | grep -i security


This can be added to a cron job or via your favorite notification method. It's part of the MOTD when you first log in, but if you are like me, you do not log out that often, so it comes in handy.