LogicMonitor-REST-Signature/lib/LogicMonitor/REST/Signature.pm

328 lines
6.6 KiB
Perl

package LogicMonitor::REST::Signature;
use 5.006;
use strict;
use warnings;
use Time::HiRes qw( gettimeofday );
use Crypt::Mac::HMAC qw( hmac_hex );
use MIME::Base64;
=head1 NAME
LogicMonitor::REST::Signature - Generate signatures and authheader info for the Logicmonitor REST API.
=head1 VERSION
Version 0.0.1
=cut
our $VERSION = '0.0.1';
=head1 SYNOPSIS
use LogicMonitor::REST::Signature;
my $company = 'someCompany';
my $accessKey = 'some key';
my $accessID = 'some id';
my $lmsig_helper;
eval {
$lmsig_helper = LogicMonitor::REST::Signature->new(
{
company => $company,
accessID => $accessID,
accessKey => $accessKey,
}
);
} if ( !defined($lmsig_helper) ) {
die( "Failed to initial the module... " . $@ );
}
my $sig;
eval{
$sig=$lmsig_helper->signature({
HTTPverb=>'GET',
path=>/foo/bar',
data=>'foo foo',
});
};
if (!defined($sig)){
die("Failed to generate the signature... ".$@);
}
=head1 VARIABLES
This is a basic explanation of various variables used in this doc.
=head2 accessID
This is the accessID for the key.
=head2 accessKey
This is the API key.
=head2 company
This is the company name as shown in the URL.
=head2 HTTPverb
This is the HTTP verb for the request in question... so either GET or PUT.
=head2 path
This is the path and any variables in the URL.
'https://' . $company . '.logicmonitor.com/santaba/rest' . $path
=head2 data
The body of the HTTP request. Can be '', if doing like a GET.
=head2 timestamp
Milliseconds since epoc.
use Time::HiRes qw( gettimeofday );
my $timestamp = gettimeofday * 1000;
$timestamp = int($timestamp);
=head1 METHODS
=head2 new
This requires a hash ref with the following three variables.
accessID
accessKey
Example...
my $lmsig_helper;
eval {
$lmsig_helper = LogicMonitor::REST::Signature->new(
{
accessID => $accessID,
accessKey => $accessKey,
}
);
} if ( !defined($lmsig_helper) ) {
die( "Failed to initial the module... " . $@ );
}
=cut
sub new {
my $args=$_[1];
if ( !defined( $_[1] ) ) {
die('No argument hash ref passed');
}
# list of required keys
my $args_valid_keys = {
# company => 1,
accessID => 1,
accessKey => 1,
};
#make sure all the keys required are present
foreach my $args_key ( keys( %{$args_valid_keys} ) ) {
if ( !defined( $args->{$args_key} ) ) {
die( 'The key "' . $args_key . '" is not present in the args hash ref' );
}
}
my $self = {
# company => $args->{company},
accessID => $args->{accessID},
accessKey => $args->{accessKey},
};
bless $self;
return $self;
}
=head2 signature
This generates the signature for a request.
This requires variables below.
HTTPverb
timestamp
path
If data is not specified, it is assumed to be ''.
data
Example...
my $sig;
eval{
$sig=$lmsig_helper->signature({
HTTPverb=>'GET',
path=>/foo/bar',
timestamp=>'1234',
});
};
if (!defined($sig)){
die("Failed to generate the signature... ".$@);
}
=cut
sub signature {
my $self = $_[0];
my $args=$_[1];
if ( !defined( $_[1] ) ) {
die('No argument hash ref passed');
}
# a list of all required keys
my $args_valid_keys = {
HTTPverb => 1,
path => 1,
timestamp => 1,
};
# make sure are the required variables are present
foreach my $args_key ( keys( %{$args_valid_keys} ) ) {
if ( !defined( $args->{$args_key} ) ) {
die( 'The key "' . $args_key . '" is not present in the args hash ref' );
}
}
# If not specified, assume it is a request it is not needed for and set it to blank.
if ( !defined( $args->{data} ) ) {
$args->{data} = '';
}
# put together the string that will be used for the signature
# https://www.logicmonitor.com/support/rest-api-developers-guide/overview/using-logicmonitors-rest-api#ss-header-24
my $string = $args->{HTTPverb} . $args->{timestamp} . $args->{data} . $args->{path};
# create the signature and return it
my $sig;
eval {
$sig = encode_base64( hmac_hex( 'SHA256', $self->{accessKey}, $string ) );
$sig =~ s/\n//g;
if ( !defined($sig) ) {
die('hmac_b64 returned undef');
}
};
if ($@) {
die( 'Failed to generate the signature... ' . $@ );
}
return $sig;
}
=sub auth_header
Generates the auth header. The usage is similiar to signature, but this does not
need a timestamp specified.
This requires variables below.
HTTPverb
path
If data is not specified, it is assumed to be ''.
data
Example...
my $auth_header;
eval{
$sig=$lmsig_helper->auth_header({
HTTPverb=>'GET',
path=>/foo/bar',
});
};
if (!defined($sig)){
die("Failed to generate the auth header... ".$@);
}
=cut
sub auth_header{
my $self = $_[0];
my $args=$_[1];
if ( !defined( $_[1] ) ) {
die('No argument hash ref passed');
}
my $timestamp = gettimeofday * 1000;
$timestamp = int($timestamp);
$args->{timestamp}=$timestamp;
my $header='LMv1 '.$self->{accessID}.':'.$self->signature($args).':'.$timestamp;
return $header;
}
=head1 AUTHOR
Zane C. Bowers-Hadley, C<< <vvelox at vvelox.net> >>
=head1 BUGS
Please report any bugs or feature requests to C<bug-logicmonitor-rest-signature at rt.cpan.org>, or through
the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=LogicMonitor-REST-Signature>. 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 LogicMonitor::REST::Signature
You can also look for information at:
=over 4
=item * RT: CPAN's request tracker (report bugs here)
L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=LogicMonitor-REST-Signature>
=item * CPAN Ratings
L<https://cpanratings.perl.org/d/LogicMonitor-REST-Signature>
=item * Search CPAN
L<https://metacpan.org/release/LogicMonitor-REST-Signature>
=item * GIT Repo
L<https://github.com/VVelox/LogicMonitor-REST-Signature>
=back
=head1 ACKNOWLEDGEMENTS
=head1 LICENSE AND COPYRIGHT
This software is Copyright (c) 2020 by Zane C. Bowers-Hadley.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)
=cut
1; # End of LogicMonitor::REST::Signature