Akamai-Edgegrid

 view release on metacpan or  search on metacpan

lib/Akamai/Edgegrid.pm  view on Meta::CPAN

=cut

our $VERSION = '1.0.5';

=head1 SYNOPSIS

    use Akamai::Edgegrid;

    my $agent = new Akamai::Edgegrid(
                    config_file => "$ENV{HOME}/.edgerc",
                    section   => "default");
    my $baseurl = "https://" . $agent->{host};

    my $resp = $agent->get("$baseurl/diagnostic-tools/v1/locations");
    print $resp->content;

=head1 DESCRIPTION

This module implements the Akamai {OPEN} Edgegrid Authentication scheme as specified by L<https://developer.akamai.com/introduction/Client_Auth.html>.

=cut

lib/Akamai/Edgegrid.pm  view on Meta::CPAN

sub _debug {
    my ($self, $msg) = @_;
    if ($self->{debug}) {
        $msg =~ s/\n$//;
        warn "$msg\n";
    }
}

sub _make_signing_key {
    my ($self, $timestamp) = @_;
    my $signing_key = _padded_hmac_sha256_base64($timestamp, $self->{client_secret});
    $self->_debug("signing_key: $signing_key");

    return $signing_key;
}

sub _canonicalize_headers {
    my ($self, $r) = @_;
    return join("\t", 
        map {
            my $header_name = lc($_);

lib/Akamai/Edgegrid.pm  view on Meta::CPAN


=item $ua = Akamai::Edgegrid->new( %options )

This method constructs a new C<Akamai::EdgeGrid> object and returns it.  This
is a subclass of C<LWP::UserAgent> and accepts all Key/value pair arguments
accepted by the parent class.  In addition The following required key/value
pairs must be provided:

    KEY           SOURCE
    ------------- -----------------------------------------------
    client_token  from "Credentials" section of Manage APIs UI
    client_secret from "Credentials" section of Manage APIs UI
    access_token  from "Authorizations" section of Manage APIs UI

The following optional key/value pairs may be provided:

    KEY             DESCRIPTION
    --------------- -------------------------------------------------------
    debug           if true enables additional logging
    headers_to_sign listref of header names to sign (in order) (default [])
    max_body        maximum body size for POSTS (default 2048)

=cut

sub new {
    my $class = shift @_;
    my %args = @_;

    my @local_args = qw(config_file section client_token client_secret access_token headers_to_sign max_body debug);
    my @required_args = qw(client_token client_secret access_token);
    my @cred_args = qw(client_token client_secret access_token host);
    my %local = ();

    for my $arg (@local_args) {
        $local{$arg} = delete $args{$arg};
    }

    my $self = LWP::UserAgent::new($class, %args);

    for my $arg (@local_args) {
        $self->{$arg} = $local{$arg};
    }

    # defaults
    unless ($self->{config_file}) {
        $self->{config_file} = "$ENV{HOME}/.edgerc";
    }
    if (-f $self->{config_file} and $self->{section} ) {
        my $cfg = Config::IniFiles->new( -file => $self->{config_file} );
        for my $variable (@cred_args) {
            if ($cfg->val($self->{section}, $variable)) {
                $self->{$variable} = $cfg->val($self->{section}, $variable);
            } else {
                die ("Config file " .  $self->{config_file} .
                    " is missing required argument " . $variable .
                    " in section " . $self->{section} );
            }
        }
        if ( $cfg->val($self->{section}, "max_body") ) {
            $self->{max_body} = $cfg->val($self->{section}, "max_body");
        }
    }

    for my $arg (@required_args) {
    unless ($self->{$arg}) {
            die "missing required argument $arg";
        }
    }

    unless ($self->{headers_to_sign}) {

t/01-testrequests.t  view on Meta::CPAN

        $json_input = <FH>;
    }
    return from_json($json_input);
}

sub run_test {
    my ($testdata, $testcase) = @_;
    note("running test: ". $testcase->{testName});
    my $ua = new Akamai::Edgegrid(
        client_token => $testdata->{client_token},
        client_secret => $testdata->{client_secret},
        access_token => $testdata->{access_token},
        headers_to_sign => $testdata->{headers_to_sign},
        max_body => $testdata->{max_body}
    );

    my $uri = new URI($testdata->{base_url});
    $uri->path_query($testcase->{request}->{path});

    my $headers = new HTTP::Headers;
    if (exists $testcase->{request}->{headers}) {

t/02-badinputs.t  view on Meta::CPAN


use 5.006;
use strict;
use warnings FATAL => 'all';
use Test::More;

use Akamai::Edgegrid;

plan tests => 4;

my @required = qw(client_token client_secret access_token);

sub test_missing {
    my $missing = shift;
    my %args = map { $_ => 'xxx' } grep { $_ ne $missing } @required;
    eval {
        new Akamai::Edgegrid(%args); 
    };
    if ($@) {
        my $msg = $@;
        like($msg, qr/^missing required argument $missing/, "missing $missing");

t/03-timestamp.t  view on Meta::CPAN

    qr/
        ^
            \d{4} # year
            [0-1][0-9] # month
            [0-3][0-9] # day
            T     
            [0-2][0-9] # hour
            :
            [0-5][0-9] # minute
            :
            [0-5][0-9] # second
            \+0000 # timezone
        $
    /x,
    'timestamp structure'
);

=head1 LICENSE AND COPYRIGHT

Copyright 2014 Akamai Technologies, Inc. All rights reserved

t/04-defaultargs.t  view on Meta::CPAN


use 5.006;
use strict;
use warnings FATAL => 'all';
use Test::More;

use Akamai::Edgegrid;

plan tests=>2;

my $ua = new Akamai::Edgegrid(client_token=>'xxx', client_secret=>'xxx',
    access_token=>'xxx');

is($ua->{max_body},131072 , 'default max_body=131072');
is_deeply($ua->{headers_to_sign}, [], 'default headers_to_sign=[]');

=head1 LICENSE AND COPYRIGHT

Copyright 2014 Akamai Technologies, Inc. All rights reserved

Licensed under the Apache License, Version 2.0 (the "License");

t/testdata.json  view on Meta::CPAN

{
    "base_url": "https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/",
    "access_token": "akab-access-token-xxx-xxxxxxxxxxxxxxxx",
    "client_token":"akab-client-token-xxx-xxxxxxxxxxxxxxxx",
    "client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=",
    "max_body": 2048,
    "headers_to_sign": [ "X-Test1", "X-Test2", "X-Test3" ],
    "nonce": "nonce-xx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "timestamp": "20140321T19:34:21+0000",
    "tests": [
        {
            "testName": "simple GET",
            "request": {
                "method": "GET",
                "path": "/",

t/testdata.json  view on Meta::CPAN

            },
            "expectedAuthorization": "EG1-HMAC-SHA256 client_token=akab-client-token-xxx-xxxxxxxxxxxxxxxx;access_token=akab-access-token-xxx-xxxxxxxxxxxxxxxx;timestamp=20140321T19:34:21+0000;nonce=nonce-xx-xxxx-xxxx-xxxx-xxxxxxxxxxxx;signature=ucq2Ab...
        },
        {
            "testName": "Header with leading and interior spaces",
            "request": {
                "method": "GET",
                "path": "/testapi/v1/t4",
                "headers": [
                    {"Host": "akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net"},
                    {"X-Test1": "     first-thing      second-thing"}
                ]
            },
            "expectedAuthorization": "EG1-HMAC-SHA256 client_token=akab-client-token-xxx-xxxxxxxxxxxxxxxx;access_token=akab-access-token-xxx-xxxxxxxxxxxxxxxx;timestamp=20140321T19:34:21+0000;nonce=nonce-xx-xxxx-xxxx-xxxx-xxxxxxxxxxxx;signature=WtnneL...
        },
        {
            "testName": "Headers out of order",
            "request": {
                "method": "GET",
                "path": "/testapi/v1/t4",
                "headers": [



( run in 0.622 second using v1.01-cache-2.11-cpan-39bf76dae61 )