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   1348 use strict;
  3         6  
  3         101  
3 3     3   11 use warnings;
  3         4  
  3         61  
4 3     3   16 use Carp;
  3         3  
  3         170  
5 3     3   1351 use Crypt::OpenSSL::RSA;
  3         18773  
  3         91  
6 3     3   1435 use Data::Validator;
  3         68812  
  3         88  
7 3     3   1373 use MIME::Base64;
  3         1673  
  3         196  
8 3     3   16 use Mouse;
  3         6  
  3         13  
9 3     3   2074 use URI;
  3         12981  
  3         1300  
10              
11             our $VERSION = "0.02";
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         177  
46 2 100       7 if ($@) {
47 1         20 croak "Private Key Error: Maybe your key is invalid. ($@)";
48             }
49 1         7 $private_key->use_sha1_hash();
50 1         3739 return $private_key;
51             }
52              
53             sub generate {
54 6     6 1 7526 my $self = shift;
55 6         32 my $args = $validator->validate(@_);
56              
57 3         184 my $resource = $args->{resource};
58 3 100       10 my $policy = exists $args->{policy} ? $args->{policy} : undef;
59 3 100       9 my $expires = exists $args->{expires} ? $args->{expires} : undef;
60              
61 3 100       10 unless ($policy) {
62 2         14 $policy = sprintf( qq/{"Statement":[{"Resource":"%s","Condition":{"DateLessThan":{"AWS:EpochTime":%d}}}]}/,
63             $resource, $expires );
64             }
65 3         9 my $encoded_policy = $self->_encode_url_safe_base64($policy);
66 3         9 my $signature = $self->_sign($policy);
67              
68 2         10 return $self->_create_url( $resource, $expires, $encoded_policy, $signature );
69             }
70              
71             sub _encode_url_safe_base64 {
72 5     5   15 my ( $self, $str ) = @_;
73 5         42 my $encoded = encode_base64($str);
74 5         14 $encoded =~ tr|+=/|-_~|;
75 5         15 return $encoded;
76             }
77              
78             sub _sign {
79 3     3   5 my ( $self, $str ) = @_;
80 3         2771 my $signature = $self->_encode_url_safe_base64( $self->private_key->sign($str) );
81 2         43 $signature =~ s/\r|\n//g;
82 2         25 return $signature;
83             }
84              
85             sub _create_url {
86 2     2   5 my ( $self, $resource, $expires, $policy, $signature ) = @_;
87 2         21 my $uri = URI->new($resource);
88 2 100       4738 if ($expires) {
89 1         17 $uri->query_form(
90             'Expires' => $expires,
91             'Signature' => $signature,
92             'Key-Pair-Id' => $self->key_pair_id(),
93             );
94             }
95             else {
96 1         9 $uri->query_form(
97             'Policy' => $policy,
98             'Signature' => $signature,
99             'Key-Pair-Id' => $self->key_pair_id(),
100             );
101             }
102 2         301 return $uri->as_string;
103             }
104              
105 3     3   17 no Mouse;
  3         4  
  3         14  
106             __PACKAGE__->meta->make_immutable;
107              
108             1;
109             __END__