From 1cd8d85025254f2069416e05b762e3a4ee63ee5e Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Thu, 5 Oct 2017 17:04:35 +1300 Subject: Add Module::Starter boilerplate for perlmodding --- lib/Mail/Cron/Crypt.pm | 141 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 lib/Mail/Cron/Crypt.pm (limited to 'lib') diff --git a/lib/Mail/Cron/Crypt.pm b/lib/Mail/Cron/Crypt.pm new file mode 100644 index 0000000..adf1c26 --- /dev/null +++ b/lib/Mail/Cron/Crypt.pm @@ -0,0 +1,141 @@ +package Mail::Cron::Crypt; + +use 5.006; +use strict; +use warnings; + +=head1 NAME + +Mail::Cron::Crypt - The great new Mail::Cron::Crypt! + +=head1 VERSION + +Version 0.01 + +=cut + +our $VERSION = '0.01'; + + +=head1 SYNOPSIS + +Quick summary of what the module does. + +Perhaps a little code snippet. + + use Mail::Cron::Crypt; + + my $foo = Mail::Cron::Crypt->new(); + ... + +=head1 EXPORT + +A list of functions that can be exported. You can delete this section +if you don't export anything, such as for a purely object-oriented module. + +=head1 SUBROUTINES/METHODS + +=head2 function1 + +=cut + +sub function1 { +} + +=head2 function2 + +=cut + +sub function2 { +} + +=head1 AUTHOR + +Tom Ryder, C<< >> + +=head1 BUGS + +Please report any bugs or feature requests to C, or through +the web interface at L. I will be notified, and then you'll +automatically be notified of progress on your bug as I make changes. + + + + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command. + + perldoc Mail::Cron::Crypt + + +You can also look for information at: + +=over 4 + +=item * RT: CPAN's request tracker (report bugs here) + +L + +=item * AnnoCPAN: Annotated CPAN documentation + +L + +=item * CPAN Ratings + +L + +=item * Search CPAN + +L + +=back + + +=head1 ACKNOWLEDGEMENTS + + +=head1 LICENSE AND COPYRIGHT + +Copyright 2017 Tom Ryder. + +This program is free software; you can redistribute it and/or modify it +under the terms of the the Artistic License (2.0). You may obtain a +copy of the full license at: + +L + +Any use, modification, and distribution of the Standard or Modified +Versions is governed by this Artistic License. By using, modifying or +distributing the Package, you accept this license. Do not use, modify, +or distribute the Package, if you do not accept this license. + +If your Modified Version has been derived from a Modified Version made +by someone other than you, you are nevertheless required to ensure that +your Modified Version complies with the requirements of this license. + +This license does not grant you the right to use any trademark, service +mark, tradename, or logo of the Copyright Holder. + +This license includes the non-exclusive, worldwide, free-of-charge +patent license to make, have made, use, offer to sell, sell, import and +otherwise transfer the Package with respect to any patent claims +licensable by the Copyright Holder that are necessarily infringed by the +Package. If you institute patent litigation (including a cross-claim or +counterclaim) against any party alleging that the Package constitutes +direct or contributory patent infringement, then this Artistic License +to you shall terminate on the date that such litigation is filed. + +Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER +AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. +THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY +YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR +CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR +CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +=cut + +1; # End of Mail::Cron::Crypt -- cgit v1.2.3 From 7969bce43d9c445d87a68080587298728d0d3e38 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Thu, 5 Oct 2017 18:06:47 +1300 Subject: Rename/separate out into app and module This still needs a lot more work before release. In particular, I have to figure out what I'm going to do about the `passphrase` option. It's probably better to both not require it, in which case no signing is done (only encryption), and to instead allow a path to a file to be specified. The other big puzzle would be how on earth to write automated tests for it... I may end up imitating however Mail::GnuPG is testing itself. --- lib/Mail/Cron/Crypt.pm | 141 ------------------------ lib/Mail/Run/Crypt.pm | 287 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 287 insertions(+), 141 deletions(-) delete mode 100644 lib/Mail/Cron/Crypt.pm create mode 100644 lib/Mail/Run/Crypt.pm (limited to 'lib') diff --git a/lib/Mail/Cron/Crypt.pm b/lib/Mail/Cron/Crypt.pm deleted file mode 100644 index adf1c26..0000000 --- a/lib/Mail/Cron/Crypt.pm +++ /dev/null @@ -1,141 +0,0 @@ -package Mail::Cron::Crypt; - -use 5.006; -use strict; -use warnings; - -=head1 NAME - -Mail::Cron::Crypt - The great new Mail::Cron::Crypt! - -=head1 VERSION - -Version 0.01 - -=cut - -our $VERSION = '0.01'; - - -=head1 SYNOPSIS - -Quick summary of what the module does. - -Perhaps a little code snippet. - - use Mail::Cron::Crypt; - - my $foo = Mail::Cron::Crypt->new(); - ... - -=head1 EXPORT - -A list of functions that can be exported. You can delete this section -if you don't export anything, such as for a purely object-oriented module. - -=head1 SUBROUTINES/METHODS - -=head2 function1 - -=cut - -sub function1 { -} - -=head2 function2 - -=cut - -sub function2 { -} - -=head1 AUTHOR - -Tom Ryder, C<< >> - -=head1 BUGS - -Please report any bugs or feature requests to C, or through -the web interface at L. I will be notified, and then you'll -automatically be notified of progress on your bug as I make changes. - - - - -=head1 SUPPORT - -You can find documentation for this module with the perldoc command. - - perldoc Mail::Cron::Crypt - - -You can also look for information at: - -=over 4 - -=item * RT: CPAN's request tracker (report bugs here) - -L - -=item * AnnoCPAN: Annotated CPAN documentation - -L - -=item * CPAN Ratings - -L - -=item * Search CPAN - -L - -=back - - -=head1 ACKNOWLEDGEMENTS - - -=head1 LICENSE AND COPYRIGHT - -Copyright 2017 Tom Ryder. - -This program is free software; you can redistribute it and/or modify it -under the terms of the the Artistic License (2.0). You may obtain a -copy of the full license at: - -L - -Any use, modification, and distribution of the Standard or Modified -Versions is governed by this Artistic License. By using, modifying or -distributing the Package, you accept this license. Do not use, modify, -or distribute the Package, if you do not accept this license. - -If your Modified Version has been derived from a Modified Version made -by someone other than you, you are nevertheless required to ensure that -your Modified Version complies with the requirements of this license. - -This license does not grant you the right to use any trademark, service -mark, tradename, or logo of the Copyright Holder. - -This license includes the non-exclusive, worldwide, free-of-charge -patent license to make, have made, use, offer to sell, sell, import and -otherwise transfer the Package with respect to any patent claims -licensable by the Copyright Holder that are necessarily infringed by the -Package. If you institute patent litigation (including a cross-claim or -counterclaim) against any party alleging that the Package constitutes -direct or contributory patent infringement, then this Artistic License -to you shall terminate on the date that such litigation is filed. - -Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER -AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. -THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY -YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR -CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR -CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -=cut - -1; # End of Mail::Cron::Crypt diff --git a/lib/Mail/Run/Crypt.pm b/lib/Mail/Run/Crypt.pm new file mode 100644 index 0000000..c37a622 --- /dev/null +++ b/lib/Mail/Run/Crypt.pm @@ -0,0 +1,287 @@ +package Mail::Run::Crypt; + +# Force me to write this properly +use strict; +use warnings; +use utf8; + +# Target Debian-Squeeze-era Perl +# We may be able to go older; not sure yet +use 5.010; + +# Import required modules +use Carp; +use Const::Fast; +use English '-no_match_vars'; +use IPC::Run3; +use Mail::GnuPG; +use MIME::Entity; + +# Specify package verson +our $VERSION = '0.01'; + +# Default exit value +const our $DEFAULT_EXIT => 127; + +# Oldschool constructor +sub new { + my ( $class, %opts ) = @_; + + # Blindly slurp in all the options given + my $self = {%opts}; + + # We must have a key ID and a recipient, but not necessarily a passphrase + for my $req (qw(keyid mailto)) { + $self->{$req} // croak "$req required"; + } + + # Default the instance name to the package name if it wasn't given; + # croncrypt(1p) will pass it in + $self->{name} //= $class; + + # Return objectified self + return bless $self, $class; +} + +# Run a given command +sub run { + my ( $self, @command ) = @_; + + # Run the command and wait for it to finish; keep its exit value for later + my ( @out, @err ); + eval { run3 \@command, undef, \@out, \@err } + or carp "Command failed: $EVAL_ERROR"; + $self->{exit} = $CHILD_ERROR >> 8; + + # If there was output, mail it + if (@out) { + my $command = join q{ }, @command; + my $subject = "$self->{name} output: $command"; + $self->_mail( $subject, \@out ); + } + + # If there were errors, mail them + if (@err) { + my $command = join q{ }, @command; + my $subject = "$self->{name} errors: $command"; + $self->_mail( $subject, \@err ); + } + + # Return status reflecting the command exit value + return $self->{exit} == 0; +} + +# Return the value of the most recently run command, or 1 otherwise +sub bail { return shift->{exit} // $DEFAULT_EXIT } + +# Send the message to the address in $ENV{MAILTO} +sub _mail { + my ( $self, $subject, $content ) = @_; + + # Build MIME object with plaintext message + my $mime = MIME::Entity->build( + To => $self->{mailto}, + Subject => $subject, + Data => $content, + ); + + # Encrypt the MIME object + my $mgpg = Mail::GnuPG->new( + key => $self->{keyid}, + passphrase => $self->{passphrase}, + ); + $mgpg->mime_signencrypt( $mime, $self->{mailto} ); + + # Send it + return $mime->send(); +} + +1; + +__END__ + +=pod + +=for stopwords +mailserver decrypt croncrypt GPG OpenPGP tradename licensable MERCHANTABILITY + +=encoding utf8 + +=head1 NAME + +Mail::Run::Crypt - Encrypt and mail output from command runs + +=head1 VERSION + +Version 0.01 + +=head1 DESCRIPTION + +This module runs commands with C, and collects any standard +output and standard error it emits. If there is any standard output or standard +error content, it is mailed (each stream separately) to a specified recipient +address. + +The idea is to allow you to view the output of automated commands while having +the content encrypted as it passes through to your mailserver, and have some +assurance that the content was actually generated by the server concerned. +C scripts are the ideal use case, but this would also with C or +anything else that might non-interactively run jobs for which output is +significant. + +You probably want to call this with the C program installed by +this distribution, which provides a means to set the properties for the module +via environment variables or command-line options. + +=head1 SYNOPSIS + + my $mrc = Mail::Run::Crypt->new( + keyid => 0x1234DEAD, + passphrase => 'extremely_insecure', + mailto => 'you@example.net', + ); + $mrc->run(qw(rsync -a /mnt/a/ remote:mnt/b)); + +=head1 SUBROUTINES/METHODS + +=head2 B + +Constructor accepts the following named parameters: + +=over 4 + +=item C + +The GnuPG key ID that should be used to encrypt the messages. + +=item C + +The passphrase used to decrypt the key. + +=item C + +The recipient email address for the content. + +=item C + +(Optional) The name of the object. When called from the C +program, this will be the string "croncrypt". + +=head2 B + +Run the specified arguments as a command with C, and email +any output or error content to the email recipient. + +=head2 B + +Return the exit status of the most recently run command, or 127 if no command +has been successfully run. + +=head1 DIAGNOSTICS + +=over 4 + +=item %s required + +One of the required properties was not passed to the constructor. + +=head1 CONFIGURATION AND ENVIRONMENT + +You will need to have a functioning GnuPG public key setup for this to work, +including the secret key. You should definitely not use your personal key; +generate one specifically for mail signing and encryption instead. + +=head1 DEPENDENCIES + +=over 4 + +=item * + +Perl v5.10.0 or newer + +=item * + +C + +=item * + +C + +=item * + +C + +=item * + +C + +=item * + +C + +=item * + +C + +=back + +=head1 INCOMPATIBILITIES + +This module uses C and other GPG-specific code, so it won't work +with any other OpenPGP implementations. + +=head1 BUGS AND LIMITATIONS + +Providing the C directly from an environment variable is not great. +The documentation needs to make that clear and offer a less bad alternative, +probably specifying the path to a secure file that it refuses to use unless it +has sufficiently restrictive permissions. + +This is very hard to test and the author has not yet figured out how to do +that. + +=head1 AUTHOR + +Tom Ryder C<< >> + +=head1 LICENSE AND COPYRIGHT + +Copyright (C) 2017 Tom Ryder + +This program is free software; you can redistribute it and/or modify it under +the terms of the Artistic License (2.0). You may obtain a copy of the full +license at: + +L + +Any use, modification, and distribution of the Standard or Modified Versions is +governed by this Artistic License. By using, modifying or distributing the +Package, you accept this license. Do not use, modify, or distribute the +Package, if you do not accept this license. + +If your Modified Version has been derived from a Modified Version made by +someone other than you, you are nevertheless required to ensure that your +Modified Version complies with the requirements of this license. + +This license does not grant you the right to use any trademark, service mark, +tradename, or logo of the Copyright Holder. + +This license includes the non-exclusive, worldwide, free-of-charge patent +license to make, have made, use, offer to sell, sell, import and otherwise +transfer the Package with respect to any patent claims licensable by the +Copyright Holder that are necessarily infringed by the Package. If you +institute patent litigation (including a cross-claim or counterclaim) against +any party alleging that the Package constitutes direct or contributory patent +infringement, then this Artistic License to you shall terminate on the date +that such litigation is filed. + +Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND +CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. +UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY +OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +=cut -- cgit v1.2.3