Amazon-CloudFront-SignedURL

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

[![Build Status](https://travis-ci.org/zoncoen/Amazon-CloudFront-SignedURL.png?branch=master)](https://travis-ci.org/zoncoen/Amazon-CloudFront-SignedURL)
# NAME

Amazon::CloudFront::SignedURL - A module to generate AWS CloudFront signed URLs.

# SYNOPSIS

    use Amazon::CloudFront::SignedURL;

    my $signed_url = Amazon::CloudFront::SignedURL->new(
        private_key_string => {PRIVATE_KEY},
        key_pair_id        => {KEY_PAIR_ID}
    );

    # create signed url with canned policy
    $signed_url->generate( resource => {RESOURCE_PATH}, expires => {EXPIRES} );

    # create signed url with custom policy
    $signed_url->generate( resource => {RESOURCE_PATH}, policy => {CUSTOM_POLICY} );

# DESCRIPTION

lib/Amazon/CloudFront/SignedURL.pm  view on Meta::CPAN


my $validator = Data::Validator->new(
    resource => { isa => 'Str', },
    expires  => {
        isa => 'Int',
        xor => [qw(policy)],
    },
    policy => { isa => 'Str', },
);

has private_key_string => (
    is       => 'rw',
    isa      => 'Str',
    required => 1,
    trigger  => sub {
        $_[0]->clear_private_key;
    },
);

has private_key => (
    is         => 'ro',
    isa        => 'Crypt::OpenSSL::RSA',
    lazy_build => 1,
);

has key_pair_id => (
    is       => 'rw',
    isa      => 'Str',
    required => 1,
);

sub _build_private_key {
    my $private_key;
    eval { $private_key = Crypt::OpenSSL::RSA->new_private_key( $_[0]->private_key_string() ); };
    if ($@) {
        croak "Private Key Error: Maybe your key is invalid. ($@)";
    }
    $private_key->use_sha1_hash();
    return $private_key;
}

sub generate {
    my $self = shift;
    my $args = $validator->validate(@_);

    my $resource = $args->{resource};
    my $policy   = exists $args->{policy} ? $args->{policy} : undef;
    my $expires  = exists $args->{expires} ? $args->{expires} : undef;

lib/Amazon/CloudFront/SignedURL.pm  view on Meta::CPAN

sub _encode_url_safe_base64 {
    my ( $self, $str ) = @_;
    my $encoded = encode_base64($str);
    $encoded =~ s/\r|\n//g;
    $encoded =~ tr|+=/|-_~|;
    return $encoded;
}

sub _sign {
    my ( $self, $str ) = @_;
    my $signature = $self->_encode_url_safe_base64( $self->private_key->sign($str) );
    return $signature;
}

sub _create_url {
    my ( $self, $resource, $expires, $policy, $signature ) = @_;
    my $uri = URI->new($resource);
    if ($expires) {
        $uri->query_form(
            'Expires'     => $expires,
            'Signature'   => $signature,

lib/Amazon/CloudFront/SignedURL.pm  view on Meta::CPAN


=head1 NAME

Amazon::CloudFront::SignedURL - A module to generate AWS CloudFront signed URLs.

=head1 SYNOPSIS

    use Amazon::CloudFront::SignedURL;

    my $signed_url = Amazon::CloudFront::SignedURL->new(
        private_key_string => {PRIVATE_KEY},
        key_pair_id        => {KEY_PAIR_ID}
    );

    # create signed url with canned policy
    $signed_url->generate( resource => {RESOURCE_PATH}, expires => {EXPIRES} );

    # create signed url with custom policy
    $signed_url->generate( resource => {RESOURCE_PATH}, policy => {CUSTOM_POLICY} );

=head1 DESCRIPTION

lib/Amazon/CloudFront/SignedURL.pm  view on Meta::CPAN

=over 4

=item C<Amazon::CloudFront::SignedURL-E<gt>new(\%args: HashRef)>

Creates a new instance.

Arguments can be:

=over 4

=item * private_key_string

The private key strings.

=item * key_pair_id

The AWS Portal assigned key pair identifier.

=back

=item C<$signed_url-E<gt>generate(\%args: HashRef)>

t/01_new.t  view on Meta::CPAN

use strict;
use warnings;
use Amazon::CloudFront::SignedURL;
use File::Basename qw(dirname);
use File::Spec;
use Test::Exception;
use Test::More;
use t::Util;

my $private_key = slurp( File::Spec->catfile( dirname(__FILE__), 'test.pem' ) );

subtest 'invalid arguments' => sub {
    throws_ok {
        Amazon::CloudFront::SignedURL->new();
    }
    qr/Attribute \(private_key_string\) is required/;

    throws_ok {
        Amazon::CloudFront::SignedURL->new( private_key_string => $private_key, );
    }
    qr/Attribute \(key_pair_id\) is required/;
};

subtest 'new' => sub {
    my $signed_url = Amazon::CloudFront::SignedURL->new(
        private_key_string => $private_key,
        key_pair_id        => 'FLSIGIOFD4CF6IDLG2DD',
    );
    isa_ok $signed_url, 'Amazon::CloudFront::SignedURL';
};

done_testing;

t/02_generate.t  view on Meta::CPAN

use strict;
use warnings;
use Amazon::CloudFront::SignedURL;
use File::Basename qw(dirname);
use File::Spec;
use Test::Exception;
use Test::More;
use t::Util;

my $private_key = slurp( File::Spec->catfile( dirname(__FILE__), 'test.pem' ) );
my $signed_url = Amazon::CloudFront::SignedURL->new(
    private_key_string => $private_key,
    key_pair_id        => 'FLSIGIOFD4CF6IDLG2DD',
);

subtest 'invalid arguments' => sub {
    throws_ok {
        $signed_url->generate();
    }
    qr/Missing parameter: 'resource'/;

    throws_ok {

t/02_generate.t  view on Meta::CPAN

            expires  => 1422494408,
            policy   => '{"Statement":[{"Resource":"test","Condition":{"DateLessThan":{"AWS:EpochTime":1422494408}}}]}',
        );
    }
    qr/Exclusive parameters passed together: 'expires' v\.s\. 'policy'/;
};

subtest 'invalid private key' => sub {
    throws_ok {
        my $signed_url = Amazon::CloudFront::SignedURL->new(
            private_key_string => 'invalid key',
            key_pair_id        => 'FLSIGIOFD4CF6IDLG2DD',
        );
        $signed_url->generate(
            resource => 'test',
            expires  => 1422494408,
        );
    }
    qr/Private Key Error: Maybe your key is invalid/;
};



( run in 0.262 second using v1.01-cache-2.11-cpan-4d50c553e7e )