Amazon-Credentials

 view release on metacpan or  search on metacpan

lib/Amazon/Credentials.pm  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
use strict;
 
use parent qw/https://metacpan.org/pod/Class::Accessor">Class::Accessor Exporter/;
 
__PACKAGE__->follow_best_practice;
__PACKAGE__->mk_accessors(qw/aws_secret_access_key aws_access_key_id token region
                             user_agent profile debug expiration role container order
                             serialized logger
                            /);
 
use JSON;
use POSIX::strptime qw/strptime/;

lib/Amazon/Credentials.pm  view on Meta::CPAN

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
use constant  AWS_IAM_SECURITY_CREDENTIALS_URL       => 'http://169.254.169.254/latest/meta-data/iam/security-credentials/';
use constant  AWS_AVAILABILITY_ZONE_URL              => 'http://169.254.169.254/latest/meta-data/placement/availability-zone';
use constant  AWS_CONTAINER_CREDENTIALS_URL          => 'http://169.254.170.2';
 
use vars qw/$VERSION @EXPORT/;
 
$VERSION = '1.0.10-1'; $VERSION=~s/\-.*$//;
 
@EXPORT = qw/$VERSION/;
 
# we only log at debug level, create a default logger
{
  no strict 'refs';
   
  *{'Amazon::Credentials::Logger::debug'} = sub {
    shift;
    my @tm = localtime(time);
    print STDERR sprintf("%s [%s] %s", strftime("%c", @tm), $$, @_);
  };
}
 
=pod
 
=head1 NAME

lib/Amazon/Credentials.pm  view on Meta::CPAN

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
to determine the order in which the class will look for credentials.
The default order is I<environent>, I<file>, I<container>, I<instance
meta-data>. See L</new>.
 
=head1 METHODS
 
=head2 new
 
 new( options );
 
 my $aws_creds = new Amazon::Credential( { profile => 'sandbox', debug => 1 });
 
C<options> is a hash of keys that represent options.  Any of the
options can also be retrieved using their corresponding 'get_{option}
method.
 
Options are listed below.
 
=over 5
 
=item aws_access_key_id
 
AWS access key.
 
=item aws_secret_access_key
 
AWS secret access key.
 
I<Note: If you pass the access keys in the constructor then the
constructor will not look in other places for credentials.>
 
=item debug
 
Set to true for verbose troubleshooting information.
 
=item logger
 
Pass in your own logger that has a C<debug()> method.  Otherwise the
default logger will output debug messages to STDERR.
 
=item user_agent
 
Pass in your own user agent, otherwise LWP will be used. I<Probably
only useful to override this for testing purposes.>
 
=item profile
 
The profile name in the configuration file (F<~/.aws/config> or
F<~/.aws/credentials>).

lib/Amazon/Credentials.pm  view on Meta::CPAN

389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
          $creds->{aws_access_key_id} = $1;
        }
        elsif (/^\s*aws_session_token\s*=\s*(.*)$/) {
          last if defined $creds->{token};
          $creds->{token} = $1;
        }
      }
         
      close $fh;
         
      $self->get_logger->debug(Dumper [ $creds ])
        if $self->get_debug;
       
      $creds->{source} = $config if $creds->{aws_secret_access_key} && $creds->{aws_access_key_id};
    }
       
    last if $creds->{source};
  };
}
 
foreach ( keys %$creds) {
  $self->set($_, $creds->{$_});

lib/Amazon/Credentials.pm  view on Meta::CPAN

438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
  if ( defined $expiration_date ) {
    # AWS recommends getting credentials 5 minutes prior to expiration
    my $g = _iso8601_to_time($expiration_date);
 
    # shave 5 minutes or window interval off of the expiration time
    $g -= $window_interval * 60;
 
    # (expiration_time - window_interval) - current_time = # of seconds left before expiration
    my $seconds_left = $g - time;
 
    if ( $self->get_debug ) {
      my $hours = int($seconds_left/3600);
      my $minutes = int(($seconds_left - $hours * 3600)/60);
      my $seconds = $seconds_left - ($hours * 3600 + $minutes * 60);
      $self->get_logger->debug(sprintf("%d hours %d minutes %d seconds until expiry\n", $hours, $minutes, $seconds));
    }
     
    $expired = ($seconds_left < 0) ? 1 : 0;
     
    $self->get_logger->debug(Dumper [ "EXPIRATION TIME: " . $expiration_date, "EXPIRED: " . $expired])
      if $self->get_debug;
  }
 
  return $expired;
}
 
sub _iso8601_to_time {
  my $iso8601 = shift;
   
  $iso8601 =~s/^(.*)Z$/$1\+00:00/;

lib/Amazon/Credentials.pm  view on Meta::CPAN

526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
  eval {
    # could be infinite, but I don't think so.  Either we get an
    # error ($@), or a non-200 response code
    while ( ! $creds->{token} ) {
       
      $url .= $role if $role;
       
      my $req = HTTP::Request->new( GET => $url );
       
      $self->get_logger->debug(Dumper [ "HTTP REQUEST:\n", $req ])
        if $self->get_debug;
       
      my $rsp = $ua->request($req);
       
      $self->get_logger->debug(Dumper [ "HTTP RESPONSE:\n", $rsp ])
        if $self->get_debug;
       
      # if not 200, then get out of Dodge
      last unless $rsp->is_success;
       
      if ( $role ) {
        $creds->{serialized} = $rsp->content;
        my $this = from_json($creds->{serialized});
        @{$creds}{qw/source role aws_access_key_id aws_secret_access_key token expiration/} =
          ('IAM',$role, @{$this}{qw/AccessKeyId SecretAccessKey Token Expiration/});
      }
      else {
        $role = $rsp->content;
        $self->get_logger->debug(Dumper ['role', $role])
          if $self->get_debug;
 
        last unless $role;
      }
    }
  };
   
  $creds->{error} = $@ if $@;
   
  $creds;
}

lib/Amazon/Credentials.pm  view on Meta::CPAN

588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
  my $self = shift;
  my $creds;
   
  if ( $self->get_role && $self->get_role eq 'ECS' ) {
    $creds = $self->get_creds_from_container;
   }
  elsif ( $self->get_role ) {
    $creds = $self->get_creds_from_role;
  }
 
  $self->get_logger->debug(Dumper [$creds])
    if $self->get_debug;
 
  die "unable to refresh token!"
    unless ref($creds);
   
  $self->set_credentials($creds);
}
 
 
sub get_creds_from_container {
  my $self = shift;

lib/Amazon/Credentials.pm  view on Meta::CPAN

611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
  my $creds = {};
   
  if ( exists $ENV{AWS_CONTAINER_CREDENTIALS_RELATIVE_URI} ) {
    # try to get credentials from instance role
    my $url = sprintf("%s%s", AWS_CONTAINER_CREDENTIALS_URL, $ENV{AWS_CONTAINER_CREDENTIALS_RELATIVE_URI});
     
    my $ua = $self->get_user_agent;
    my $req = HTTP::Request->new( GET => $url );
    $req->header("Accept", "*/*");
     
    $self->get_logger->debug(Dumper [ "HTTP REQUEST:\n", $req ])
      if $self->get_debug;
 
    $self->get_logger->debug(Dumper [ $req->as_string ])
      if $self->get_debug;
     
    my $rsp = $ua->request($req);
     
    $self->get_logger->debug(Dumper [ "HTTP RESPONSE:\n", $rsp ])
      if $self->get_debug;
     
    # if not 200, then get out of Dodge
    if ( $rsp->is_success ) {
      $creds->{serialized} = $rsp->content;
      my $this = from_json($rsp->content);
      @{$creds}{qw/source container aws_access_key_id aws_secret_access_key token expiration/} =
        ('IAM','ECS', @{$this}{qw/AccessKeyId SecretAccessKey Token Expiration/});
    }
    else {
      $self->get_logger->debug( "return code: " . $rsp->status_line . "\n");
    }
     
    $creds->{error} = $@ if $@;
  }
   
  $creds;
}
 
=pod

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

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
aws_access_key_id=bar-aws-access-key-id
aws_secret_access_key=bar-aws-secret-access-key
eot
  close $fh;
  "$home/.aws/credentials";
};
 
$ENV{HOME} = "$home";
$ENV{AWS_PROFILE} = undef;
 
my $creds = new Amazon::Credentials({ order => [qw/file/], debug => $ENV{DEBUG} ? 1 : 0 });
ok(ref($creds), 'find credentials');
 
my %new_creds = (
                 aws_access_key_id     => 'biz-aws-access-key-id',
                 aws_secret_access_key => 'biz-aws-secret-access-key',
                 token                 => 'biz',
                 expiration            => time2str("%Y-%m-%dT%H:%M:%SZ", time + -5 + (5 * 60), "GMT")
                );
 
$creds->set_credentials(\%new_creds);



( run in 0.511 second using v1.01-cache-2.11-cpan-3cd7ad12f66 )