| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Mojo::UserAgent::Role::AWSSignature4; |
|
2
|
1
|
|
|
1
|
|
465729
|
use Mojo::Base -role, -signatures; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
3974
|
use Digest::SHA; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
42
|
|
|
5
|
1
|
|
|
1
|
|
6
|
use Mojo::Collection; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
26
|
|
|
6
|
1
|
|
|
1
|
|
555
|
use Time::Piece; |
|
|
1
|
|
|
|
|
6676
|
|
|
|
1
|
|
|
|
|
4
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '0.01'; |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
has access_key => sub { $ENV{AWS_ACCESS_KEY} or die 'missing "access_key"' }; |
|
11
|
|
|
|
|
|
|
has aws_algorithm => 'AWS4-HMAC-SHA256'; |
|
12
|
|
|
|
|
|
|
has content => undef; |
|
13
|
|
|
|
|
|
|
has debug => 0; |
|
14
|
|
|
|
|
|
|
has expires => 86_400; |
|
15
|
|
|
|
|
|
|
has region => 'us-east-1'; |
|
16
|
|
|
|
|
|
|
has secret_key => sub { $ENV{AWS_SECRET_KEY} or die 'missing "secret_key"' }; |
|
17
|
|
|
|
|
|
|
has service => sub { die 'missing "service"' }; |
|
18
|
|
|
|
|
|
|
has session_token => sub { $ENV{AWS_SESSION_TOKEN} || undef }; |
|
19
|
|
|
|
|
|
|
has unsigned_payload => 0; |
|
20
|
|
|
|
|
|
|
has _tx => sub {die}; |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
around build_tx => sub ($orig, $self, @args) { |
|
23
|
|
|
|
|
|
|
$self->transactor->add_generator( |
|
24
|
|
|
|
|
|
|
awssig4 => sub { |
|
25
|
|
|
|
|
|
|
my ($transactor, $tx, $config) = @_; |
|
26
|
|
|
|
|
|
|
my $aws = $self->new({%$config, _tx => $tx}); |
|
27
|
|
|
|
|
|
|
$tx->req->content->asset(Mojo::Asset::File->new(path => $aws->content)) if $aws->content; |
|
28
|
|
|
|
|
|
|
$tx->req->headers->host($tx->req->url->host || 'localhost'); |
|
29
|
|
|
|
|
|
|
$tx->req->headers->header('X-Amz-Date' => $aws->date_timestamp); |
|
30
|
|
|
|
|
|
|
$tx->req->headers->header('X-Amz-Content-Sha256' => $aws->hashed_payload); |
|
31
|
|
|
|
|
|
|
$tx->req->headers->header('X-Amz-Expires' => $aws->expires) if $aws->expires; |
|
32
|
|
|
|
|
|
|
$tx->req->headers->authorization($aws->authorization); |
|
33
|
|
|
|
|
|
|
} |
|
34
|
|
|
|
|
|
|
); |
|
35
|
|
|
|
|
|
|
$orig->($self, @args); |
|
36
|
|
|
|
|
|
|
}; |
|
37
|
|
|
|
|
|
|
|
|
38
|
3
|
|
|
3
|
1
|
50
|
sub authorization ($self) { |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
7
|
|
|
39
|
3
|
|
|
|
|
11
|
sprintf '%s Credential=%s/%s, SignedHeaders=%s, Signature=%s', $self->aws_algorithm, $self->access_key, |
|
40
|
|
|
|
|
|
|
$self->credential_scope, $self->signed_header_list, $self->signature; |
|
41
|
|
|
|
|
|
|
} |
|
42
|
|
|
|
|
|
|
|
|
43
|
7
|
|
|
7
|
1
|
634
|
sub canonical_headers ($self) { |
|
|
7
|
|
|
|
|
13
|
|
|
|
7
|
|
|
|
|
11
|
|
|
44
|
7
|
|
|
|
|
10
|
join '', map { lc($_) . ":" . $self->_tx->req->headers->to_hash->{$_} . "\n" } @{$self->header_list}; |
|
|
41
|
|
|
|
|
3399
|
|
|
|
7
|
|
|
|
|
18
|
|
|
45
|
|
|
|
|
|
|
} |
|
46
|
|
|
|
|
|
|
|
|
47
|
7
|
|
|
7
|
1
|
988
|
sub canonical_qstring { shift->_tx->req->url->query->to_string } |
|
48
|
|
|
|
|
|
|
|
|
49
|
7
|
|
|
7
|
1
|
3693
|
sub canonical_request ($self) { |
|
|
7
|
|
|
|
|
11
|
|
|
|
7
|
|
|
|
|
10
|
|
|
50
|
|
|
|
|
|
|
Mojo::Collection->new( |
|
51
|
|
|
|
|
|
|
$self->_tx->req->method, |
|
52
|
|
|
|
|
|
|
$self->_tx->req->url->path->to_abs_string, |
|
53
|
|
|
|
|
|
|
$self->canonical_qstring, $self->canonical_headers, $self->signed_header_list, $self->hashed_payload |
|
54
|
|
|
|
|
|
|
)->tap(sub { |
|
55
|
7
|
100
|
|
7
|
|
810
|
warn $_->map(sub {"CR:$_"})->join("\n") if $self->debug; |
|
|
30
|
|
|
|
|
180
|
|
|
56
|
7
|
|
|
|
|
20
|
})->join("\n"); |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
|
|
59
|
8
|
|
|
8
|
1
|
754
|
sub credential_scope ($self) { |
|
|
8
|
|
|
|
|
16
|
|
|
|
8
|
|
|
|
|
13
|
|
|
60
|
8
|
|
|
|
|
21
|
join '/', $self->date, $self->region, $self->service, 'aws4_request'; |
|
61
|
|
|
|
|
|
|
} |
|
62
|
|
|
|
|
|
|
|
|
63
|
13
|
|
|
13
|
1
|
41
|
sub date { shift->time->ymd('') } |
|
64
|
|
|
|
|
|
|
|
|
65
|
6
|
|
|
6
|
1
|
82
|
sub date_timestamp { $_[0]->time->ymd('') . 'T' . $_[0]->time->hms('') . 'Z' } |
|
66
|
|
|
|
|
|
|
|
|
67
|
10
|
|
|
10
|
1
|
4662
|
sub hashed_payload ($self) { |
|
|
10
|
|
|
|
|
15
|
|
|
|
10
|
|
|
|
|
19
|
|
|
68
|
10
|
100
|
|
|
|
35
|
$self->unsigned_payload ? 'UNSIGNED-PAYLOAD' : Digest::SHA::sha256_hex($self->_tx->req->body); |
|
69
|
|
|
|
|
|
|
} |
|
70
|
|
|
|
|
|
|
|
|
71
|
18
|
|
|
18
|
1
|
28
|
sub header_list { [sort keys %{shift->_tx->req->headers->to_hash}] } |
|
|
18
|
|
|
|
|
47
|
|
|
72
|
|
|
|
|
|
|
|
|
73
|
4
|
|
|
4
|
1
|
22
|
sub signature ($self) { |
|
|
4
|
|
|
|
|
8
|
|
|
|
4
|
|
|
|
|
6
|
|
|
74
|
4
|
|
|
|
|
13
|
Digest::SHA::hmac_sha256_hex($self->string_to_sign, $self->signing_key); |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub signed_header_list { |
|
78
|
11
|
|
|
11
|
1
|
1558
|
join ';', map { lc($_) } @{shift->header_list}; |
|
|
64
|
|
|
|
|
1251
|
|
|
|
11
|
|
|
|
|
30
|
|
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
|
|
81
|
1
|
|
|
1
|
1
|
2840
|
sub signed_qstring ($self) { |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
3
|
|
|
82
|
1
|
|
|
|
|
6
|
$self->_tx->req->url->query(['X-Amz-Signature' => $self->signature]); |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
|
|
85
|
5
|
|
|
5
|
1
|
213
|
sub signing_key ($self) { |
|
|
5
|
|
|
|
|
11
|
|
|
|
5
|
|
|
|
|
12
|
|
|
86
|
5
|
|
|
|
|
18
|
my $kSecret = "AWS4" . $self->secret_key; |
|
87
|
5
|
|
|
|
|
38
|
my $kDate = Digest::SHA::hmac_sha256($self->date, $kSecret); |
|
88
|
5
|
|
|
|
|
158
|
my $kRegion = Digest::SHA::hmac_sha256($self->region, $kDate); |
|
89
|
5
|
|
|
|
|
63
|
my $kService = Digest::SHA::hmac_sha256($self->service, $kRegion); |
|
90
|
5
|
|
|
|
|
132
|
Digest::SHA::hmac_sha256("aws4_request", $kService); |
|
91
|
|
|
|
|
|
|
} |
|
92
|
|
|
|
|
|
|
|
|
93
|
4
|
|
|
4
|
1
|
6
|
sub string_to_sign ($self) { |
|
|
4
|
|
|
|
|
6
|
|
|
|
4
|
|
|
|
|
6
|
|
|
94
|
|
|
|
|
|
|
Mojo::Collection->new($self->aws_algorithm, $self->date_timestamp, $self->credential_scope, |
|
95
|
|
|
|
|
|
|
Digest::SHA::sha256_hex($self->canonical_request))->tap(sub { |
|
96
|
4
|
100
|
|
4
|
|
472
|
warn $_->map(sub {"STS:$_"})->join("\n") if $self->debug; |
|
|
12
|
|
|
|
|
92
|
|
|
97
|
4
|
|
|
|
|
14
|
})->join("\n"); |
|
98
|
|
|
|
|
|
|
} |
|
99
|
|
|
|
|
|
|
|
|
100
|
0
|
|
|
0
|
|
|
sub time {gmtime} |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
1; |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
__END__ |