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__ |