File Coverage

blib/lib/Amazon/CloudFront/SignedURL.pm
Criterion Covered Total %
statement 58 58 100.0
branch 10 10 100.0
condition n/a
subroutine 14 14 100.0
pod 1 1 100.0
total 83 83 100.0


line stmt bran cond sub pod time code
1             package Amazon::CloudFront::SignedURL;
2 3     3   1380 use strict;
  3         10  
  3         101  
3 3     3   12 use warnings;
  3         4  
  3         65  
4 3     3   19 use Carp;
  3         3  
  3         191  
5 3     3   1395 use Crypt::OpenSSL::RSA;
  3         16827  
  3         93  
6 3     3   1360 use Data::Validator;
  3         69423  
  3         96  
7 3     3   1484 use MIME::Base64;
  3         1634  
  3         228  
8 3     3   17 use Mouse;
  3         5  
  3         16  
9 3     3   5096 use URI;
  3         13373  
  3         1383  
10              
11             our $VERSION = "0.01";
12              
13             my $validator = Data::Validator->new(
14             resource => { isa => 'Str', },
15             expires => {
16             isa => 'Int',
17             xor => [qw(policy)],
18             },
19             policy => { isa => 'Str', },
20             );
21              
22             has private_key_string => (
23             is => 'rw',
24             isa => 'Str',
25             required => 1,
26             trigger => sub {
27             $_[0]->clear_private_key;
28             },
29             );
30              
31             has private_key => (
32             is => 'ro',
33             isa => 'Crypt::OpenSSL::RSA',
34             lazy_build => 1,
35             );
36              
37             has key_pair_id => (
38             is => 'rw',
39             isa => 'Str',
40             required => 1,
41             );
42              
43             sub _build_private_key {
44 2     2   1 my $private_key;
45 2         4 eval { $private_key = Crypt::OpenSSL::RSA->new_private_key( $_[0]->private_key_string() ); };
  2         164  
46 2 100       6 if ($@) {
47 1         22 croak "Private Key Error: Maybe your key is invalid. ($@)";
48             }
49 1         5 $private_key->use_sha1_hash();
50 1         4269 return $private_key;
51             }
52              
53             sub generate {
54 6     6 1 8311 my $self = shift;
55 6         25 my $args = $validator->validate(@_);
56              
57 3         144 my $resource = $args->{resource};
58 3 100       9 my $policy = exists $args->{policy} ? $args->{policy} : undef;
59 3 100       7 my $expires = exists $args->{expires} ? $args->{expires} : undef;
60              
61 3 100       8 unless ($policy) {
62 2         9 $policy = sprintf( qq/{"Statement":[{"Resource":"%s","Condition":{"DateLessThan":{"AWS:EpochTime":%d}}}]}/,
63             $resource, $expires );
64             }
65 3         8 my $encoded_policy = $self->_encode_url_safe_base64($policy);
66 3         8 my $signature = $self->_sign($policy);
67              
68 2         7 return $self->_create_url( $resource, $expires, $encoded_policy, $signature );
69             }
70              
71             sub _encode_url_safe_base64 {
72 5     5   9 my ( $self, $str ) = @_;
73 5         28 my $encoded = encode_base64($str);
74 5         11 $encoded =~ tr|+=/|-_~|;
75 5         11 return $encoded;
76             }
77              
78             sub _sign {
79 3     3   3 my ( $self, $str ) = @_;
80 3         2590 my $signature = $self->_encode_url_safe_base64( $self->private_key->sign($str) );
81 2         31 $signature =~ s/\r|\n//g;
82 2         20 return $signature;
83             }
84              
85             sub _create_url {
86 2     2   4 my ( $self, $resource, $expires, $policy, $signature ) = @_;
87 2         13 my $uri = URI->new($resource);
88 2 100       4386 if ($expires) {
89 1         8 $uri->query_form(
90             'Expires' => $expires,
91             'Signature' => $signature,
92             'Key-Pair-Id' => $self->key_pair_id(),
93             );
94             }
95             else {
96 1         6 $uri->query_form(
97             'Policy' => $policy,
98             'Signature' => $signature,
99             'Key-Pair-Id' => $self->key_pair_id(),
100             );
101             }
102 2         255 return $uri;
103             }
104              
105 3     3   18 no Mouse;
  3         6  
  3         20  
106             __PACKAGE__->meta->make_immutable;
107              
108             1;
109             __END__