File Coverage

blib/lib/Net/Amazon/S3/Signature/V2.pm
Criterion Covered Total %
statement 78 83 93.9
branch 15 20 75.0
condition 14 16 87.5
subroutine 15 16 93.7
pod 2 3 66.6
total 124 138 89.8


line stmt bran cond sub pod time code
1             # ABSTRACT: V2 signatures
2             $Net::Amazon::S3::Signature::V2::VERSION = '0.991';
3             use Moose;
4 99     99   646 use URI::Escape qw( uri_escape_utf8 );
  99         206  
  99         566  
5 99     99   522280 use HTTP::Date qw[ time2str ];
  99         277  
  99         4150  
6 99     99   562 use MIME::Base64 qw( encode_base64 );
  99         216  
  99         4085  
7 99     99   540 use URI::QueryParam;
  99         190  
  99         3397  
8 99     99   551 use URI;
  99         201  
  99         2432  
9 99     99   505  
  99         196  
  99         2095  
10             use Net::Amazon::S3::Constants;
11 99     99   525  
  99         183  
  99         2471  
12             use namespace::clean;
13 99     99   566  
  99         203  
  99         932  
14             extends 'Net::Amazon::S3::Signature';
15              
16             my $AMAZON_HEADER_PREFIX = 'x-amz-';
17              
18             0;
19             }
20 1     1 0 24  
21             my ($self, $request) = @_;
22              
23             $self->_add_auth_header( $request );
24 209     209 1 107258 }
25              
26 209         1059 my ($self, $request, $expires) = @_;
27              
28             my $aws_access_key_id = $self->http_request->s3->aws_access_key_id;
29              
30 2     2 1 7 my $canonical_string = $self->_canonical_string( $request, $expires );
31             my $encoded_canonical = $self->_encode( $canonical_string );
32 2         52  
33             my $uri = URI->new( $request->uri );
34 2         8  
35 2         5 $uri->query_param( AWSAccessKeyId => $aws_access_key_id );
36             $uri->query_param( Expires => $expires );
37 2         7 $uri->query_param( Signature => $encoded_canonical );
38              
39 2         138 $uri->as_string;
40 2         191 }
41 2         240  
42             my ( $self, $request ) = @_;
43 2         314  
44             my $aws_access_key_id = $self->http_request->s3->aws_access_key_id;
45             my $aws_secret_access_key = $self->http_request->s3->aws_secret_access_key;
46              
47 209     209   468 if ( not $request->headers->header('Date') ) {
48             $request->header( Date => time2str(time) );
49 209         5327 }
50 209         4948  
51             $self->_append_authorization_headers ($request);
52 209 50       718  
53 209         8051 my $canonical_string = $self->_canonical_string( $request );
54             my $encoded_canonical = $self->_encode( $canonical_string );
55             $request->header( Authorization => "AWS $aws_access_key_id:$encoded_canonical" );
56 209         13144 }
57              
58 209         687 my ( $self, $request, $expires ) = @_;
59 209         746 my $method = $request->method;
60 209         1021 my $path = $self->http_request->path;
61              
62             my %interesting_headers = ();
63             for my $key ($request->headers->header_field_names) {
64 211     211   535 my $lk = lc $key;
65 211         617 if ( $lk eq 'content-md5'
66 211         6762 or $lk eq 'content-type'
67             or $lk eq 'date'
68 211         451 or $lk =~ /^$AMAZON_HEADER_PREFIX/ )
69 211         535 {
70 574         6680 $interesting_headers{$lk} = $self->_trim( $request->header( $lk ) );
71 574 100 100     3754 }
      100        
      100        
72             }
73              
74             # these keys get empty strings if they don't exist
75             $interesting_headers{'content-type'} ||= '';
76 353         871 $interesting_headers{'content-md5'} ||= '';
77              
78             # just in case someone used this. it's not necessary in this lib.
79             $interesting_headers{'date'} = ''
80             if $interesting_headers{Net::Amazon::S3::Constants->HEADER_DATE};
81 211   100     939  
82 211   100     884 # if you're using expires for query string auth, then it trumps date
83             # (and x-amz-date)
84             $interesting_headers{'date'} = $expires if $expires;
85              
86 211 50       1462 my $buf = "$method\n";
87             foreach my $key ( sort keys %interesting_headers ) {
88             if ( $key =~ /^$AMAZON_HEADER_PREFIX/ ) {
89             $buf .= "$key:$interesting_headers{$key}\n";
90 211 100       459 } else {
91             $buf .= "$interesting_headers{$key}\n";
92 211         491 }
93 211         863 }
94 696 100       1900  
95 63         190 # don't include anything after the first ? in the resource...
96             $path =~ /^([^?]*)/;
97 633         1399 $buf .= "/$1";
98              
99             # ...unless there any parameters we're interested in...
100             if ( $path =~ /[&?](acl|torrent|location|uploads|delete)($|=|&)/ ) {
101             $buf .= "?$1";
102 211         726 } elsif ( my %query_params = URI->new($path)->query_form ){
103 211         627 #see if the remaining parsed query string provides us with any query string or upload id
104             if($query_params{partNumber} && $query_params{uploadId}){
105             #re-evaluate query string, the order of the params is important for request signing, so we can't depend on URI to do the right thing
106 211 100       1459 $buf .= sprintf("?partNumber=%s&uploadId=%s", $query_params{partNumber}, $query_params{uploadId});
    100          
107 56         138 }
108             elsif($query_params{uploadId}){
109             $buf .= sprintf("?uploadId=%s",$query_params{uploadId});
110 12 50 33     1312 }
    50          
111             }
112 0         0  
113             return $buf;
114             }
115 0         0  
116             # finds the hmac-sha1 hash of the canonical string and the aws secret access key and then
117             # base64 encodes the result (optionally urlencoding after that).
118             my ( $self, $str, $urlencode ) = @_;
119 211         9632 my $hmac = Digest::HMAC_SHA1->new($self->http_request->s3->aws_secret_access_key);
120             $hmac->add($str);
121             my $b64 = encode_base64( $hmac->digest, '' );
122             if ($urlencode) {
123             return $self->_urlencode($b64);
124             } else {
125 211     211   486 return $b64;
126 211         5786 }
127 211         9325 }
128 211         1664  
129 211 50       5562 my ( $self, $unencoded ) = @_;
130 0         0 return uri_escape_utf8( $unencoded, '^A-Za-z0-9_-' );
131             }
132 211         1345  
133             my ( $self, $value ) = @_;
134             $value =~ s/^\s+//;
135             $value =~ s/\s+$//;
136             return $value;
137 0     0   0 }
138 0         0  
139             1;
140              
141              
142 353     353   12752 =pod
143 353         853  
144 353         950 =encoding UTF-8
145 353         1098  
146             =head1 NAME
147              
148             Net::Amazon::S3::Signature::V2 - V2 signatures
149              
150             =head1 VERSION
151              
152             version 0.991
153              
154             =head1 AUTHOR
155              
156             Branislav Zahradník <barney@cpan.org>
157              
158             =head1 COPYRIGHT AND LICENSE
159              
160             This software is copyright (c) 2022 by Amazon Digital Services, Leon Brocard, Brad Fitzpatrick, Pedro Figueiredo, Rusty Conover, Branislav Zahradník.
161              
162             This is free software; you can redistribute it and/or modify it under
163             the same terms as the Perl 5 programming language system itself.
164              
165             =cut