File Coverage

blib/lib/Net/Amazon/AWSSign.pm
Criterion Covered Total %
statement 64 66 96.9
branch 7 14 50.0
condition n/a
subroutine 12 12 100.0
pod 3 4 75.0
total 86 96 89.5


line stmt bran cond sub pod time code
1             package Net::Amazon::AWSSign;
2              
3 1     1   28312 use 5.008;
  1         3  
  1         39  
4 1     1   6 use strict;
  1         1  
  1         33  
5 1     1   4 use warnings;
  1         7  
  1         38  
6              
7 1     1   5 use vars qw($VERSION);
  1         2  
  1         60  
8             $VERSION = '0.12';
9              
10 1     1   1018 use MIME::Base64;
  1         833  
  1         74  
11 1     1   53474 use Digest::SHA qw(hmac_sha256_base64);
  1         7473  
  1         250  
12 1     1   1051 use URI::Escape;
  1         2167  
  1         1144  
13              
14              
15             # General stuff
16             my $request;
17             my $SOAPAction;
18             my $SOAPTimestamp;
19             my @params;
20             my $finalString='';
21             my $finalParams='';
22             my $AWSSignature='';
23             my $finalRequestURL;
24             # My throwaway temp arrays
25             my @a;
26             my @b;
27             # My throwaway temp variables
28             my $z;
29             my $y;
30             # For the secret generator
31             my $requestProtocol;
32             my $requestHost;
33             my $requestPath;
34              
35              
36             ## OO Subs
37             # Construct an object, called with your AWS key and secret
38             sub new
39             {
40 1     1 1 15 my $class = shift;
41 1         18 my $self = {
42             _AWSKey => shift,
43             _AWSSecret => shift,
44             };
45 1         3 bless $self, $class;
46 1         3 return $self;
47             }
48              
49              
50             sub addRESTSecret {
51 1     1 1 6 my ($self, $request)=@_;
52 1 50       6 unless ($request=~m/\&Timestamp=2/) {
53 0         0 $request=$request . "&Timestamp=" . &getAWSTimeStamp();
54             }
55 1         3 $finalString="GET\n";
56             # Not sure why I thought this was important, but I probably had some rationale, so leaving it in here.
57 1 50       10 if ($request=~m/^(http|https)?:\/\/(.*?)\/(.*?)\?/) {
58 1         2 $requestProtocol="$1";
59 1         3 $requestHost="$2";
60 1         3 $requestPath="/$3";
61 1         7 $finalString=$finalString . "$2\n/$3\n";
62             }else{
63 0         0 return "ERROR: Cannot determine hostname and base path of request";
64             }
65             # Get just the parameters
66 1         6 @a=split(/\?/, $request, 2);
67             # If we don't already have the subscription ID in the argument list, then add it.
68 1 50       20 unless ($a[1]=~m/$self->{_AWSKey}/) { $a[1]="$a[1]&AWSAccessKeyId=$self->{_AWSKey}"; }
  1         5  
69             # Ditto for the SHA version and Signature version
70 1 50       5 unless ($a[1]=~m/HmacSHA256/) { $a[1]="$a[1]&SignatureMethod=HmacSHA256"; }
  1         4  
71 1 50       4 unless ($a[1]=~m/SignatureVersion/) { $a[1]="$a[1]&SignatureVersion=2"; }
  1         3  
72              
73 1         9 @params=split(/\&/, $a[1]);
74             # Sort and URI encode arguments, slam them into @b
75 1         4 undef @b;
76 1         8 foreach $z (sort @params) {
77 9         25 @a=split(/=/, $z, 2);
78             # To allow for passing in url-encoded strings, we decode it then encode it
79 9         32 $a[1]=URI::Escape::uri_unescape( "$a[1]");
80 9         73 $a[1]=URI::Escape::uri_escape( "$a[1]", "^A-Za-z0-9\-_.~" );
81 9         448 $z=join('=', @a);
82 9         18 push (@b, $z);
83             }
84 1         6 $finalString="$finalString" . join ('&', @b);
85              
86 1         36 $AWSSignature=hmac_sha256_base64("$finalString", "$self->{_AWSSecret}");
87             # For some reason we usually need an equals sign appended. Check if required
88 1 50       5 unless ($AWSSignature=~m/=$/) { $AWSSignature=$AWSSignature . "="; }
  1         2  
89 1         4 $AWSSignature=URI::Escape::uri_escape( "$AWSSignature", "^A-Za-z0-9\-_.~" );
90 1         37 return "$requestProtocol://" . $requestHost . $requestPath . "?" . join ('&', @b) . "&Signature=" . $AWSSignature;
91             }
92              
93             sub SOAPSig {
94 1     1 1 691 my ($self, $SOAPAction)=@_;
95 1         4 $SOAPTimestamp=&getAWSTimeStamp();
96 1         4 $finalString=$SOAPAction . $SOAPTimestamp;
97 1         13 $AWSSignature=hmac_sha256_base64("$finalString", "$self->{_AWSSecret}");
98             # For some reason we usually need an equals sign appended. Check if required
99 1 50       5 unless ($AWSSignature=~m/=$/) { $AWSSignature=$AWSSignature . "="; }
  1         2  
100 1         3 @a=("$SOAPTimestamp", "$AWSSignature");
101 1         23 return @a;
102             }
103              
104              
105             ## Internal subs
106             sub getAWSTimeStamp {
107             # The Timestamp must be generated in a specific format.
108             return sprintf("%04d-%02d-%02dT%02d:%02d:%02d.000Z",
109 1     1   9 sub { ($_[5]+1900,
110             $_[4]+1,
111             $_[3],
112             $_[2],
113             $_[1],
114             $_[0])
115 1     1 0 22 }->(gmtime(time)));
116             }
117              
118             1;
119              
120             __END__