File Coverage

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


line stmt bran cond sub pod time code
1             package Amazon::CloudFront::SignedURL;
2 3     3   1572 use strict;
  3         7  
  3         107  
3 3     3   10 use warnings;
  3         3  
  3         65  
4 3     3   19 use Carp;
  3         4  
  3         187  
5 3     3   1404 use Crypt::OpenSSL::RSA;
  3         63156  
  3         139  
6 3     3   1747 use Data::Validator;
  3         77923  
  3         110  
7 3     3   1658 use MIME::Base64;
  3         1737  
  3         227  
8 3     3   19 use Mouse;
  3         7  
  3         17  
9 3     3   2503 use URI;
  3         14304  
  3         1424  
10              
11             our $VERSION = "0.03";
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   2 my $private_key;
45 2         4 eval { $private_key = Crypt::OpenSSL::RSA->new_private_key( $_[0]->private_key_string() ); };
  2         203  
46 2 100       7 if ($@) {
47 1         20 croak "Private Key Error: Maybe your key is invalid. ($@)";
48             }
49 1         6 $private_key->use_sha1_hash();
50 1         3921 return $private_key;
51             }
52              
53             sub generate {
54 6     6 1 7320 my $self = shift;
55 6         31 my $args = $validator->validate(@_);
56              
57 3         223 my $resource = $args->{resource};
58 3 100       12 my $policy = exists $args->{policy} ? $args->{policy} : undef;
59 3 100       7 my $expires = exists $args->{expires} ? $args->{expires} : undef;
60              
61 3 100       9 if ($policy) {
62 1         4 $policy =~ s/ //g;
63             }
64             else {
65 2         11 $policy = sprintf( qq/{"Statement":[{"Resource":"%s","Condition":{"DateLessThan":{"AWS:EpochTime":%d}}}]}/,
66             $resource, $expires );
67             }
68 3         9 my $encoded_policy = $self->_encode_url_safe_base64($policy);
69 3         9 my $signature = $self->_sign($policy);
70              
71 2         7 return $self->_create_url( $resource, $expires, $encoded_policy, $signature );
72             }
73              
74             sub _encode_url_safe_base64 {
75 5     5   11 my ( $self, $str ) = @_;
76 5         33 my $encoded = encode_base64($str);
77 5         56 $encoded =~ s/\r|\n//g;
78 5         10 $encoded =~ tr|+=/|-_~|;
79 5         13 return $encoded;
80             }
81              
82             sub _sign {
83 3     3   5 my ( $self, $str ) = @_;
84 3         2625 my $signature = $self->_encode_url_safe_base64( $self->private_key->sign($str) );
85 2         23 return $signature;
86             }
87              
88             sub _create_url {
89 2     2   3 my ( $self, $resource, $expires, $policy, $signature ) = @_;
90 2         18 my $uri = URI->new($resource);
91 2 100       4777 if ($expires) {
92 1         13 $uri->query_form(
93             'Expires' => $expires,
94             'Signature' => $signature,
95             'Key-Pair-Id' => $self->key_pair_id(),
96             );
97             }
98             else {
99 1         6 $uri->query_form(
100             'Policy' => $policy,
101             'Signature' => $signature,
102             'Key-Pair-Id' => $self->key_pair_id(),
103             );
104             }
105 2         235 return $uri->as_string;
106             }
107              
108 3     3   22 no Mouse;
  3         4  
  3         20  
109             __PACKAGE__->meta->make_immutable;
110              
111             1;
112             __END__