diff options
author | Tom Ryder <tom@sanctum.geek.nz> | 2014-02-14 11:16:34 +1300 |
---|---|---|
committer | Tom Ryder <tom@sanctum.geek.nz> | 2014-02-14 11:16:34 +1300 |
commit | ac03f31601545551a44f256379fb02cc8f8b4ce7 (patch) | |
tree | 229b72b32547f160f21e02f0beb8df3c0efe1e4a | |
parent | Initial commit (diff) | |
download | Mail-Run-Crypt-ac03f31601545551a44f256379fb02cc8f8b4ce7.tar.gz Mail-Run-Crypt-ac03f31601545551a44f256379fb02cc8f8b4ce7.zip |
First code commit
Very bare bones at the moment. Needs perldoc or man(1) help and possibly
a Makefile to install it.
-rw-r--r-- | README.markdown | 45 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rwxr-xr-x | croncrypt | 125 |
3 files changed, 170 insertions, 4 deletions
diff --git a/README.markdown b/README.markdown new file mode 100644 index 0000000..f877739 --- /dev/null +++ b/README.markdown @@ -0,0 +1,45 @@ +Croncrypt +========= + +Wrapper to sign and encrypt `cron(8)` output and errors with PGP/MIME before +sending them to the default MAILTO destination. + + CRONCRYPT_KEYID=0x0A1B2C3D4E5F6G7H + CRONCRYPT_PASSPHRASE=hibbityboo + MAILTO=tom@sanctum.geek.nz + 0 1 * * * tom croncrypt rsync /home/tom/important-file /home/backups + +The main design goal is simplicity; just whack `croncrypt` in front of all your +`crontab(5)` entries, provided they don't use pipes or stderr/stdout redirects, +in which case you should consider putting it all into a script file anyway. + +Don't use your own GPG key for signing! I recommend you create a dedicated key +just for Croncrypt, and sign it locally with `gpg --lsign` so that your +software trusts it locally. + +Installation +------------ + +Put the `croncrypt` binary somewhere in your `crontab`'s `PATH`, and install +the following Perl modules: + +* `Carp` +* `Data::Dumper` +* `IPC::Open3` +* `Mail::GnuPG` +* `MIME::Entity` +* `Symbol` + +On Debian-derived systems, this should do the trick: + + # aptitude install perl-base perl-modules \ + libmail-gnupg-perl libmime-tools-perl + +License +------- + +Copyright (c) [Tom Ryder][1]. Distributed under Perl's [Artistic License][2]. + +[1]: http://www.sanctum.geek.nz/about/tom-ryder +[2]: http://dev.perl.org/licenses/artistic.html + diff --git a/README.md b/README.md deleted file mode 100644 index 4068725..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -croncrypt -========= - -Sign and encrypt cron(8) output diff --git a/croncrypt b/croncrypt new file mode 100755 index 0000000..1c09047 --- /dev/null +++ b/croncrypt @@ -0,0 +1,125 @@ +#!/usr/bin/env perl + +# +# croncrypt: Wrapper to sign and encrypt cron output and errors with PGP/MIME +# before sending them to the default MAILTO destination. +# +# CRONCRYPT_KEYID=0x0A1B2C3D4E5F6G7H +# CRONCRYPT_PASSPHRASE=hibbityboo +# MAILTO=tom@sanctum.geek.nz +# 0 1 * * * tom croncrypt rsync /home/tom/important-file /home/backups +# +# The main design goal is simplicity; just whack a «croncrypt» in front of all +# your cron tasks, provided they don't use pipes or stderr/stdout redirects, +# in which case you should consider putting it all into a script file anyway. +# +# Don't use your own GPG key for signing! Create a dedicated key just for +# croncrypt, and sign it locally with «gpg --lsign» maybe. +# +# Author: Tom Ryder <tom@sanctum.geek.nz> +# Copyright: 2014 Sanctum +# License: Artistic <http://dev.perl.org/licenses/artistic.html> +# +# $Id$ +# +package Sanctum::Croncrypt; + +# Force me to write this properly +use strict; +use warnings; + +# Decree package version to pacify Perl::Critic +our $VERSION = 0.1; + +# Pull in some required modules +use Carp; +use Data::Dumper; +use IPC::Open3; +use Mail::GnuPG; +use MIME::Entity; +use Symbol 'gensym'; + +# Bail if run without arguments +if ( !@ARGV ) { + printf "%s\n", 'USAGE: croncrypt <command>'; + exit 1; +} + +# Bail if we don't have the environment variables we need +my @fails = (); +if ( !exists $ENV{'CRONCRYPT_KEYID'} ) { + push @fails, 'CRONCRYPT_KEYID is not set; set it to your key ID.'; +} +if ( !exists $ENV{'CRONCRYPT_PASSPHRASE'} ) { + push @fails, + 'CRONCRYPT_PASSPHRASE is not set; set it to your key\'s passphrase.'; +} +if ( !exists $ENV{'MAILTO'} ) { + push @fails, 'MAILTO is not set; set it to the message\'s destination.'; +} +if (@fails) { + foreach my $fail (@fails) { + printf {*STDERR} "croncrypt: FAIL: %s\n", $fail; + } + exit 1; +} + +# Read details from environment +my $recipient = $ENV{MAILTO}; +my $key = $ENV{CRONCRYPT_KEYID}; +my $passphrase = $ENV{CRONCRYPT_PASSPHRASE}; + +# Establish filehandles; need to specifically create symbol for stderr +my ( $stdin, $stdout, $stderr ); +$stderr = gensym; + +# Run the command in the arguments and wait for it to finish +my $pid = open3( $stdin, $stdout, $stderr, @ARGV ); +waitpid $pid, 0; + +# Read any and all output and errors +my @output = <$stdout>; +my @errors = <$stderr>; + +# Close the filehandles, placating Perl::Critic with return checks +close $stdin + or croak('Could not close stdin'); +close $stdout + or croak('Could not close stdout'); +close $stderr + or croak('Could not close stderr'); + +# If there was output, mail it +if (@output) { + my $subject = sprintf 'croncrypt output: %s', join q{ }, @ARGV; + mail( $subject, \@output ); +} + +# If there were errors, mail them +if (@errors) { + my $subject = sprintf 'croncrypt errors: %s', join q{ }, @ARGV; + mail( $subject, \@errors ); +} + +# Send the message to the address in $ENV{MAILTO} +sub mail { + my ( $subject, $content ) = @_; + + # Build MIME object with plaintext message + my $mime = MIME::Entity->build( + To => $recipient, + Subject => $subject, + Data => $content, + ); + + # Encrypt the MIME object + my $mgpg = Mail::GnuPG->new( + key => $key, + passphrase => $passphrase, + ); + $mgpg->mime_signencrypt( $mime, $recipient ); + + # Send it + return $mime->send(); +} + |