File Coverage

blib/lib/Net/Amazon/IAM.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package Net::Amazon::IAM;
2 1     1   12433 use Moose;
  1         296304  
  1         6  
3              
4 1     1   4950 use URI;
  1         2742  
  1         20  
5 1     1   4 use Carp;
  1         4  
  1         47  
6 1     1   488 use JSON;
  1         7223  
  1         3  
7 1     1   435 use URI::Encode;
  1         7342  
  1         35  
8 1     1   151 use XML::Simple;
  0            
  0            
9             use POSIX qw(strftime);
10             use LWP::UserAgent;
11             use LWP::Protocol::https;
12             use Data::Dumper qw(Dumper);
13             use Params::Validate qw(validate SCALAR ARRAYREF HASHREF);
14             use HTTP::Request::Common;
15             use AWS::Signature4;
16              
17             use Net::Amazon::IAM::Error;
18             use Net::Amazon::IAM::Errors;
19             use Net::Amazon::IAM::User;
20             use Net::Amazon::IAM::Users;
21             use Net::Amazon::IAM::Policy;
22             use Net::Amazon::IAM::Policies;
23             use Net::Amazon::IAM::UserPolicy;
24             use Net::Amazon::IAM::PolicyVersion;
25             use Net::Amazon::IAM::PolicyVersions;
26             use Net::Amazon::IAM::Group;
27             use Net::Amazon::IAM::Groups;
28             use Net::Amazon::IAM::GroupPolicy;;
29             use Net::Amazon::IAM::GetGroupResult;
30             use Net::Amazon::IAM::AccessKey;
31             use Net::Amazon::IAM::AccessKeyMetadata;
32             use Net::Amazon::IAM::AccessKeysList;
33             use Net::Amazon::IAM::Role;
34             use Net::Amazon::IAM::Roles;
35             use Net::Amazon::IAM::VirtualMFADevice;
36             use Net::Amazon::IAM::VirtualMFADevices;
37             use Net::Amazon::IAM::MFADevice;
38             use Net::Amazon::IAM::MFADevices;
39             use Net::Amazon::IAM::InstanceProfile;
40             use Net::Amazon::IAM::InstanceProfiles;
41             use Net::Amazon::IAM::LoginProfile;
42              
43             our $VERSION = '0.05';
44              
45             =head1 NAME
46              
47             Net::Amazon::IAM - Perl interface to the Amazon Identity and Access Management.
48              
49             =head1 VERSION
50              
51             This is Net::Amazon::IAM version 0.05
52              
53             IAM Query API version: '2010-05-08'
54              
55             =head1 SYNOPSIS
56              
57             use Net::Amazon::IAM;
58              
59             my $iam = Net::Amazon::IAM->new(
60             AWSAccessKeyId => 'PUBLIC_KEY_HERE',
61             SecretAccessKey => 'SECRET_KEY_HERE',
62             return_errors => 0, # which is default
63             );
64              
65             # prepare user policy document
66             my $policy_document = {
67             Version => '2012-10-17',
68             Statement => [
69             {
70             Effect => 'Allow',
71             Action => [
72             's3:Get*',
73             's3:List*',
74             ],
75             Resource => [
76             'arn:aws:s3:::sometestbucket',
77             'arn:aws:s3:::sometestbucket/*',
78             ],
79             },
80             ],
81             };
82              
83             try {
84             # create new user
85             my $user = $iam->create_user(
86             UserName => 'testuser',
87             Path => '/path/to/test/users/',
88             );
89            
90             # Add an inline user policy document.
91             my $policy = $iam->put_user_policy (
92             PolicyName => 'somtestpolicy',
93             UserName => 'sometestuser',
94             PolicyDocument => $policy_document,
95             );
96              
97             print $user->UserId . "\n";
98             print $policy->PolicyId . "\n";
99             } catch {
100             my $error = shift();
101             print $error->as_string() . "\n";
102             }
103              
104             If an error occurs while communicating with IAM, these methods will
105             throw a L<Net::Amazon::IAM::Error> exception.
106              
107             =head1 DESCRIPTION
108              
109             This module is a Perl interface to Amazon's Identity and Access Management (IAM). It uses the Query API to
110             communicate with Amazon's Web Services framework.
111              
112             =head1 CLASS METHODS
113              
114             =head2 new(%params)
115              
116             This is the constructor, it will return you a Net::Amazon::IAM object to work with. It takes
117             these parameters:
118              
119             =over
120              
121             =item AWSAccessKeyId (required)
122              
123             Your AWS access key.
124              
125             =item SecretAccessKey (required)
126              
127             Your secret key, B<WARNING!> don't give this out or someone will be able to use your account
128             and incur charges on your behalf.
129              
130             =item debug (optional)
131              
132             A flag to turn on debugging. Among other useful things, it will make the failing api calls print
133             a stack trace. It is turned off by default.
134              
135             =item return_errors (optional)
136              
137             A flag to enable returning errors as objects instead of throwing them as exceptions.
138              
139             =back
140              
141             =cut
142              
143             has 'AWSAccessKeyId' => (
144             is => 'ro',
145             isa => 'Str',
146             lazy => 1,
147             default => sub {
148             if (defined($_[0]->temp_creds)) {
149             return $_[0]->temp_creds->{'AccessKeyId'};
150             } else {
151             return undef;
152             }
153             }
154             );
155              
156             has 'SecretAccessKey' => (
157             is => 'ro',
158             isa => 'Str',
159             lazy => 1,
160             default => sub {
161             if (defined($_[0]->temp_creds)) {
162             return $_[0]->temp_creds->{'SecretAccessKey'};
163             } else {
164             return undef;
165             }
166             }
167             );
168              
169             has 'SecurityToken' => (
170             is => 'ro',
171             isa => 'Str',
172             lazy => 1,
173             predicate => 'has_SecurityToken',
174             default => sub {
175             if (defined($_[0]->temp_creds)) {
176             return $_[0]->temp_creds->{'Token'};
177             } else {
178             return undef;
179             }
180             }
181             );
182              
183             has 'base_url' => (
184             is => 'ro',
185             isa => 'Str',
186             lazy => 1,
187             default => sub {
188             return 'http' . ($_[0]->ssl ? 's' : '') . '://iam.amazonaws.com';
189             }
190             );
191              
192             has 'temp_creds' => (
193             is => 'ro',
194             lazy => 1,
195             predicate => 'has_temp_creds',
196             default => sub {
197             my $ret;
198             $ret = $_[0]->_fetch_iam_security_credentials();
199             },
200             );
201              
202             has 'debug' => ( is => 'ro', isa => 'Str', default => 0 );
203             has 'version' => ( is => 'ro', isa => 'Str', default => '2010-05-08' );
204             has 'ssl' => ( is => 'ro', isa => 'Bool', default => 1 );
205             has 'return_errors' => ( is => 'ro', isa => 'Bool', default => 0 );
206              
207             sub _timestamp {
208             return strftime("%Y-%m-%dT%H:%M:%SZ",gmtime);
209             }
210              
211             sub _fetch_iam_security_credentials {
212             my $self = shift;
213             my $retval = {};
214              
215             my $ua = LWP::UserAgent->new();
216             # Fail quickly if this is not running on an EC2 instance
217             $ua->timeout(2);
218              
219             my $url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/';
220              
221             $self->_debug("Attempting to fetch instance credentials");
222              
223             my $res = $ua->get($url);
224             if ($res->code == 200) {
225             # Assumes the first profile is the only profile
226             my $profile = (split /\n/, $res->content())[0];
227              
228             $res = $ua->get($url . $profile);
229              
230             if ($res->code == 200) {
231             $retval->{'Profile'} = $profile;
232             foreach (split /\n/, $res->content()) {
233             return undef if /Code/ && !/Success/;
234             if (m/.*"([^"]+)"\s+:\s+"([^"]+)",/) {
235             $retval->{$1} = $2;
236             }
237             }
238              
239             return $retval if (keys %{$retval});
240             }
241             }
242              
243             return undef;
244             }
245              
246             sub _sign {
247             my $self = shift;
248             my %args = @_;
249             my $action = delete $args{'Action'};
250             my %sign_hash = %args;
251             my $timestamp = $self->_timestamp;
252              
253             $sign_hash{'Action'} = $action;
254             $sign_hash{'Version'} = $self->version;
255              
256             if ($self->has_temp_creds || $self->has_SecurityToken) {
257             $sign_hash{'SecurityToken'} = $self->SecurityToken;
258             }
259              
260             my $signer = AWS::Signature4->new(
261             -access_key => $self->{'AWSAccessKeyId'},
262             -secret_key => $self->{'SecretAccessKey'},
263             );
264              
265             my $ua = LWP::UserAgent->new();
266              
267             my $request = POST(
268             $self->base_url,
269             [
270             %sign_hash,
271             ],
272             );
273              
274             $signer->sign($request);
275              
276             my $res = $ua->request($request);
277              
278             # We should force <item> elements to be in an array
279             my $xs = XML::Simple->new(
280             ForceArray => qr/(?:item|Errors)/i, # Always want item elements unpacked to arrays
281             KeyAttr => '', # Turn off folding for 'id', 'name', 'key' elements
282             SuppressEmpty => undef, # Turn empty values into explicit undefs
283             );
284             my $xml;
285              
286             # Check the result for connectivity problems, if so throw an error
287             if ($res->code >= 500) {
288             my $message = $res->status_line;
289             $xml = <<EOXML;
290             <xml>
291             <RequestID>N/A</RequestID>
292             <Errors>
293             <Error>
294             <Code>HTTP POST FAILURE</Code>
295             <Message>$message</Message>
296             </Error>
297             </Errors>
298             </xml>
299             EOXML
300              
301             } else {
302             $xml = $res->content();
303             }
304              
305             my $ref = $xs->XMLin($xml);
306             warn Dumper($ref) . "\n\n" if $self->debug == 1;
307              
308             return $ref;
309             }
310              
311             sub _parse_errors {
312             my $self = shift;
313             my $errors_xml = shift;
314              
315             my $es;
316             my $request_id = $errors_xml->{'RequestId'};
317              
318             my $error = Net::Amazon::IAM::Error->new(
319             code => $errors_xml->{'Error'}{'Code'},
320             message => $errors_xml->{'Error'}{'Message'},
321             request_id => $request_id,
322             );
323              
324             if ($self->return_errors) {
325             return $error;
326             }
327              
328             # Print a stack trace if debugging is enabled
329             if ($self->debug) {
330             confess 'Last error was: ' . $error->message;
331             }else{
332             croak $error;
333             }
334             }
335              
336             sub _debug {
337             my $self = shift;
338             my $message = shift;
339              
340             if ((grep { defined && length} $self->debug) && $self->debug == 1) {
341             print "$message\n\n\n\n";
342             }
343             }
344              
345             sub _build_filters {
346             my ($self, $args) = @_;
347              
348             my $filters = delete $args->{Filter};
349              
350             return unless $filters && ref($filters) eq 'ARRAY';
351              
352             $filters = [ $filters ] unless ref($filters->[0]) eq 'ARRAY';
353             my $count = 1;
354             foreach my $filter (@{$filters}) {
355             my ($name, @args) = @$filter;
356             $args->{"Filter." . $count.".Name"} = $name;
357             $args->{"Filter." . $count.".Value.".$_} = $args[$_-1] for 1..scalar @args;
358             $count++;
359             }
360             }
361              
362             sub _parse_attributes {
363             my $self = shift;
364             my $single_object = shift;
365             my $list_objects = shift;
366             my %result = @_;
367              
368             my $attributes;
369             if ( grep { defined && length } $result{$list_objects}{'member'} ) {
370             if(ref($result{$list_objects}{'member'}) eq 'ARRAY') {
371             for my $attr(@{$result{$list_objects}{'member'}}) {
372             my $a = "Net::Amazon::IAM::$single_object"->new(
373             $attr,
374             );
375             push @$attributes, $a;
376             }
377             }else{
378             my $a = "Net::Amazon::IAM::$single_object"->new(
379             $result{$list_objects}{'member'},
380             );
381             push @$attributes, $a;
382             }
383             }else{
384             $attributes = [];
385             }
386              
387             return $attributes;
388             }
389              
390             =head2 create_user(%params)
391              
392             Create new IAM user
393              
394             =over
395              
396             =item UserName (required)
397              
398             New user username
399              
400             =item Path (optional)
401              
402             Where to create new user
403              
404             =back
405              
406             Returns a L<Net::Amazon::IAM::User> object on success or L<Net::Amazon::IAM::Error> on fail.
407              
408             =cut
409              
410             sub create_user {
411             my $self = shift;
412              
413             my %args = validate(@_, {
414             UserName => { type => SCALAR },
415             Path => { type => SCALAR, optional => 1 },
416             });
417              
418             my $xml = $self->_sign(Action => 'CreateUser', %args);
419              
420             if ( grep { defined && length } $xml->{'Error'} ) {
421             return $self->_parse_errors($xml);
422             } else {
423             return Net::Amazon::IAM::User->new(
424             $xml->{'CreateUserResult'}{'User'},
425             );
426             }
427             }
428              
429             =head2 delete_user(%params)
430              
431             Delete IAM User
432              
433             =over
434              
435             =item UserName (required)
436              
437             What user should be deleted
438              
439             =back
440              
441             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
442              
443             =cut
444              
445             sub delete_user {
446             my $self = shift;
447              
448             my %args = validate(@_, {
449             UserName => { type => SCALAR },
450             });
451              
452             my $xml = $self->_sign(Action => 'DeleteUser', %args);
453              
454             if ( grep { defined && length } $xml->{'Error'} ) {
455             return $self->_parse_errors($xml);
456             } else {
457             return 1;
458             }
459             }
460              
461             =head2 get_user(%params)
462              
463             Get IAM user details
464              
465             =over
466              
467             =item UserName (required)
468              
469             New user username
470              
471             =back
472              
473             Returns a L<Net::Amazon::IAM::User> object on success or L<Net::Amazon::IAM::Error> on fail.
474              
475             =cut
476              
477             sub get_user {
478             my $self = shift;
479              
480             my %args = validate(@_, {
481             UserName => { type => SCALAR },
482             });
483              
484             my $xml = $self->_sign(Action => 'GetUser', %args);
485              
486             if ( grep { defined && length } $xml->{'Error'} ) {
487             return $self->_parse_errors($xml);
488             } else {
489             return Net::Amazon::IAM::User->new(
490             $xml->{'GetUserResult'}{'User'},
491             );
492             }
493             }
494              
495             =head2 update_user(%params)
496              
497             Updates the name and/or the path of the specified user.
498              
499             =over
500              
501             =item UserName (required)
502              
503             Name of the user to update. If you're changing the name of the user, this is the original user name.
504              
505             =item NewPath (optional)
506              
507             New path for the user. Include this parameter only if you're changing the user's path.
508              
509             =item NewUserName (optional)
510              
511             New name for the user. Include this parameter only if you're changing the user's name.
512              
513             =back
514              
515             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
516              
517             =cut
518              
519             sub update_user {
520             my $self = shift;
521              
522             my %args = validate(@_, {
523             UserName => { type => SCALAR },
524             NewPath => { type => SCALAR, optional => 1 },
525             NewUserName => { type => SCALAR, optional => 1 },
526             });
527              
528             my $xml = $self->_sign(Action => 'UpdateUser', %args);
529              
530             if ( grep { defined && length } $xml->{'Error'} ) {
531             return $self->_parse_errors($xml);
532             } else {
533             return 1;
534             }
535             }
536              
537             =head2 list_users(%params)
538              
539             Lists the IAM users that have the specified path prefix.
540             If no path prefix is specified, the action returns all users in the AWS account.
541              
542             =over
543              
544             =item Marker (required)
545              
546             Use this parameter only when paginating results, and only in a subsequent request
547             after you've received a response where the results are truncated. Set it to the
548             value of the Marker element in the response you just received.
549              
550             =item MaxItems (optional)
551              
552             Use this parameter only when paginating results to indicate the maximum number of
553             user names you want in the response. If there are additional user names beyond the
554             maximum you specify, the IsTruncated response element is true. This parameter is
555             optional. If you do not include it, it defaults to 100.
556              
557             =item PathPrefix (optional)
558              
559             The path prefix for filtering the results. For example:
560             /division_abc/subdivision_xyz/, which would get all user
561             names whose path starts with /division_abc/subdivision_xyz/.
562              
563             =back
564              
565             Returns L<Net::Amazon::IAM::Users> object on success or L<Net::Amazon::IAM::Error> on fail.
566              
567             =cut
568              
569             sub list_users {
570             my $self = shift;
571              
572             my %args = validate(@_, {
573             Marker => { type => SCALAR, optional => 1 },
574             MaxItems => { type => SCALAR, optional => 1 },
575             PathPrefix => { type => SCALAR, optional => 1 },
576             });
577              
578             my $xml = $self->_sign(Action => 'ListUsers', %args);
579              
580             if ( grep { defined && length } $xml->{'Error'} ) {
581             return $self->_parse_errors($xml);
582             } else {
583             my %result = %{$xml->{'ListUsersResult'}};
584             my $users = $self->_parse_attributes('User', 'Users', %result);
585              
586             return Net::Amazon::IAM::Users->new(
587             Users => $users,
588             IsTruncated => $result{'IsTruncated'},
589             Marker => $result{'Marker'},
590             );
591             }
592             }
593              
594             =head2 add_user_to_group(%params)
595              
596             Adds the specified user to the specified group.
597              
598             =over
599              
600             =item GroupName (required)
601              
602             The name of the group to update.
603              
604             =item UserName (required)
605              
606             The name of the user to add.
607              
608             =back
609              
610             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
611              
612             =cut
613              
614             sub add_user_to_group {
615             my $self = shift;
616              
617             my %args = validate(@_, {
618             GroupName => { type => SCALAR },
619             UserName => { type => SCALAR },
620             });
621              
622             my $xml = $self->_sign(Action => 'AddUserToGroup', %args);
623              
624             if ( grep { defined && length } $xml->{'Error'} ) {
625             return $self->_parse_errors($xml);
626             } else {
627             return 1;
628             }
629             }
630              
631             =head2 remove_user_from_group(%params)
632              
633             Removes the specified user from the specified group.
634              
635             =over
636              
637             =item GroupName (required)
638              
639             The name of the group to update.
640              
641             =item UserName (required)
642              
643             The name of the user to remove.
644              
645             =back
646              
647             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
648              
649             =cut
650              
651             sub remove_user_from_group {
652             my $self = shift;
653              
654             my %args = validate(@_, {
655             GroupName => { type => SCALAR },
656             UserName => { type => SCALAR },
657             });
658              
659             my $xml = $self->_sign(Action => 'RemoveUserFromGroup', %args);
660              
661             if ( grep { defined && length } $xml->{'Error'} ) {
662             return $self->_parse_errors($xml);
663             } else {
664             return 1;
665             }
666             }
667              
668             =head2 create_group(%params)
669              
670             Creates a new group.
671              
672             =over
673              
674             =item GroupName (required)
675              
676             The name of the group to create.
677              
678             =item Path (optional)
679              
680             The path to the group.
681              
682             =back
683              
684             Returns L<Net::Amazon::IAM::Group> object on success or L<Net::Amazon::IAM::Error> on fail.
685              
686             =cut
687              
688             sub create_group {
689             my $self = shift;
690              
691             my %args = validate(@_, {
692             GroupName => { type => SCALAR },
693             Path => { type => SCALAR, optional => 1 },
694             });
695              
696             my $xml = $self->_sign(Action => 'CreateGroup', %args);
697              
698             if ( grep { defined && length } $xml->{'Error'} ) {
699             return $self->_parse_errors($xml);
700             } else {
701             return Net::Amazon::IAM::Group->new(
702             $xml->{'CreateGroupResult'}{'User'},
703             );
704             }
705             }
706              
707             =head2 get_group(%params)
708              
709             Returns group details and list of users that are in the specified group.
710              
711             =over
712              
713             =item GroupName (required)
714              
715             The name of the group.
716              
717             =item MaxItems (optional)
718              
719             Use this only when paginating results to indicate the maximum number of
720             groups you want in the response. If there are additional groups beyond the
721             maximum you specify, the IsTruncated response element is true. This parameter is optional.
722             If you do not include it, it defaults to 100.
723              
724             =item Marker (optional)
725              
726             Use this only when paginating results, and only in a subsequent request
727             after you've received a response where the results are truncated.
728             Set it to the value of the Marker element in the response you just received.
729              
730             =back
731              
732             Returns L<Net::Amazon::IAM::GetGroupResult> object on success or L<Net::Amazon::IAM::Error> on fail.
733              
734             =cut
735              
736             sub get_group {
737             my $self = shift;
738              
739             my %args = validate(@_, {
740             GroupName => { type => SCALAR },
741             Marker => { type => SCALAR, optional => 1 },
742             MaxItems => { type => SCALAR, optional => 1 },
743             });
744              
745             my $xml = $self->_sign(Action => 'GetGroup', %args);
746              
747             if ( grep { defined && length } $xml->{'Error'} ) {
748             return $self->_parse_errors($xml);
749             } else {
750             my %result = %{$xml->{'GetGroupResult'}};
751             my $users = $self->_parse_attributes('User', 'Users', %result);
752              
753             my $group = Net::Amazon::IAM::Group->new(
754             %{$result{'Group'}},
755             );
756              
757             return Net::Amazon::IAM::GetGroupResult->new(
758             IsTruncated => $result{'IsTruncated'},
759             Marker => $result{'Marker'},
760             Users => $users,
761             Group => $group,
762             );
763             }
764             }
765              
766             =head2 delete_group(%params)
767              
768             Deletes the specified group. The group must not contain any users or have any attached policies.
769              
770             =over
771              
772             =item GroupName (required)
773              
774             The name of the group to delete.
775              
776             =back
777              
778             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
779              
780             =cut
781              
782             sub delete_group {
783             my $self = shift;
784              
785             my %args = validate(@_, {
786             GroupName => { type => SCALAR },
787             });
788              
789             my $xml = $self->_sign(Action => 'DeleteGroup', %args);
790              
791             if ( grep { defined && length } $xml->{'Error'} ) {
792             return $self->_parse_errors($xml);
793             } else {
794             return 1;
795             }
796             }
797              
798             =head2 list_groups(%params)
799              
800             Lists the groups that have the specified path prefix.
801              
802             =over
803              
804             =item Marker (optional)
805              
806             Use this only when paginating results, and only in a subsequent request after
807             you've received a response where the results are truncated. Set it to the value
808             of the Marker element in the response you just received.
809              
810             =item MaxItems (optional)
811              
812             Use this only when paginating results to indicate the maximum number of groups
813             you want in the response. If there are additional groups beyond the maximum you specify,
814             the IsTruncated response element is true. This parameter is optional. If you do not include
815             it, it defaults to 100.
816              
817             =item PathPrefix (optional)
818              
819             The path prefix for filtering the results. For example, the prefix /division_abc/subdivision_xyz/
820             gets all groups whose path starts with /division_abc/subdivision_xyz/.
821              
822             =back
823              
824             Returns L<Net::Amazon::IAM::Groups> object on success or L<Net::Amazon::IAM::Error> on fail.
825              
826             =cut
827              
828             sub list_groups {
829             my $self = shift;
830              
831             my %args = validate(@_, {
832             Marker => { type => SCALAR, optional => 1 },
833             MaxItems => { type => SCALAR, optional => 1 },
834             PathPrefix => { type => SCALAR, optional => 1 },
835             });
836              
837             my $xml = $self->_sign(Action => 'ListGroups', %args);
838              
839             if ( grep { defined && length } $xml->{'Error'} ) {
840             return $self->_parse_errors($xml);
841             } else {
842             my %result = %{$xml->{'ListGroupsResult'}};
843             my $groups = $self->_parse_attributes('Group', 'Groups', %result);
844              
845             return Net::Amazon::IAM::Groups->new(
846             Groups => $groups,
847             IsTruncated => $result{'IsTruncated'},
848             Marker => $result{'Marker'},
849             );
850             }
851             }
852              
853             =head2 create_policy(%params)
854              
855             Creates a new managed policy for your AWS account.
856              
857             =over
858              
859             =item PolicyName (required)
860              
861             The name of the policy document.
862              
863             =item PolicyDocument (required)
864              
865             The policy document.
866              
867             =item Description (optional)
868              
869             A friendly description of the policy.
870              
871             =item Path (optional)
872              
873             The path for the policy.
874              
875             =back
876              
877             Returns L<Net::Amazon::IAM::Policy> object on success or L<Net::Amazon::IAM::Error> on fail.
878              
879             =cut
880              
881             sub create_policy {
882             my $self = shift;
883              
884             my %args = validate(@_, {
885             PolicyName => { type => SCALAR },
886             PolicyDocument => { type => HASHREF },
887             Description => { type => SCALAR, optional => 1 },
888             Path => { type => SCALAR, optional => 1 },
889             });
890              
891             $args{'PolicyDocument'} = encode_json delete $args{'PolicyDocument'};
892              
893             my $xml = $self->_sign(Action => 'CreatePolicy', %args);
894              
895             if ( grep { defined && length } $xml->{'Error'} ) {
896             return $self->_parse_errors($xml);
897             } else {
898             return Net::Amazon::IAM::Policy->new(
899             $xml->{'CreatePolicyResult'}{'Policy'},
900             );
901             }
902             }
903              
904             =head2 get_policy(%params)
905              
906             Retrieves information about the specified managed policy.
907              
908             =over
909              
910             =item PolicyArn (required)
911              
912             The Amazon Resource Name (ARN). ARNs are unique identifiers for AWS resources.
913              
914             =back
915              
916             Returns L<Net::Amazon::IAM::Policy> object on success or L<Net::Amazon::IAM::Error> on fail.
917              
918             =cut
919              
920             sub get_policy {
921             my $self = shift;
922              
923             my %args = validate(@_, {
924             PolicyArn => { type => SCALAR },
925             });
926              
927             my $xml = $self->_sign(Action => 'GetPolicy', %args);
928              
929             if ( grep { defined && length } $xml->{'Error'} ) {
930             return $self->_parse_errors($xml);
931             } else {
932             return Net::Amazon::IAM::Policy->new(
933             $xml->{'GetPolicyResult'}{'Policy'},
934             );
935             }
936             }
937              
938             =head2 delete_policy(%params)
939              
940             Deletes the specified managed policy.
941              
942             =over
943              
944             =item PolicyArn (required)
945              
946             The Amazon Resource Name (ARN). ARNs are unique identifiers for AWS resources.
947              
948             =back
949              
950             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
951              
952             =cut
953              
954             sub delete_policy {
955             my $self = shift;
956              
957             my %args = validate(@_, {
958             PolicyArn => { type => SCALAR },
959             });
960              
961             my $xml = $self->_sign(Action => 'DeletePolicy', %args);
962              
963             if ( grep { defined && length } $xml->{'Error'} ) {
964             return $self->_parse_errors($xml);
965             } else {
966             return 1;
967             }
968             }
969              
970             =head2 list_policies(%params)
971              
972             Lists all the managed policies that are available to your account,
973             including your own customer managed policies and all AWS managed policies.
974              
975             You can filter the list of policies that is returned using the optional
976             OnlyAttached, Scope, and PathPrefix parameters. For example, to list only the
977             customer managed policies in your AWS account, set Scope to Local.
978             To list only AWS managed policies, set Scope to AWS.
979              
980             =over
981              
982             =item OnlyAttached (optional)
983              
984             A flag to filter the results to only the attached policies.
985             When OnlyAttached is true, the returned list contains only the
986             policies that are attached to a user, group, or role.
987             When OnlyAttached is false, or when the parameter is not
988             included, all policies are returned.
989              
990             =item PathPrefix (optional)
991              
992             The path prefix for filtering the results.
993             If it is not included, it defaults to a slash (/), listing all policies.
994              
995             =item Scope (optional)
996              
997             The scope to use for filtering the results.
998              
999             To list only AWS managed policies, set Scope to AWS.
1000             To list only the customer managed policies in your AWS account, set Scope to Local.
1001             If it is not included, or if it is set to All, all policies are returned.
1002              
1003             =item MaxItems (optional)
1004              
1005             Maximum number of policies to retrieve.
1006              
1007             =item Marker (optional)
1008              
1009             If IsTruncated is true, this element is present and contains the value to use for the
1010             Marker parameter in a subsequent pagination request.
1011              
1012             Example:
1013             my $policies = $iam->list_policies(
1014             MaxItems => 1
1015             );
1016              
1017             while($policies->IsTruncated eq 'true') {
1018             for my $policy(@{$policies->{'Policies'}}) {
1019             print $policy->PolicyId . "\n";
1020             }
1021              
1022             $policies = $iam->list_policies(
1023             MaxItems => 50,
1024             Marker => $policies->Marker,
1025             );
1026             }
1027              
1028             =back
1029              
1030             Returns L<Net::Amazon::IAM::Policies> on success or L<Net::Amazon::IAM::Error> on fail.
1031             When no policies found, the Policies attribute will be just empty array.
1032              
1033             =cut
1034              
1035             sub list_policies {
1036             my $self = shift;
1037              
1038             my %args = validate(@_, {
1039             Marker => { type => SCALAR, optional => 1 },
1040             MaxItems => { type => SCALAR, optional => 1 },
1041             PathPrefix => { type => SCALAR, optional => 1, default => '/' },
1042             OnlyAttached => { regex => qr/true|false/, optional => 1, default => 'false' },
1043             Scope => { regex => qr/AWS|Local|All/, optional => 1, default => 'All' },
1044             });
1045              
1046             my $xml = $self->_sign(Action => 'ListPolicies', %args);
1047              
1048             if ( grep { defined && length } $xml->{'Error'} ) {
1049             return $self->_parse_errors($xml);
1050             } else {
1051             my %result = %{$xml->{'ListPoliciesResult'}};
1052             my $policies = $self->_parse_attributes('Policy', 'Policies', %result);
1053              
1054             return Net::Amazon::IAM::Policies->new(
1055             Policies => $policies,
1056             IsTruncated => $result{'IsTruncated'},
1057             Marker => $result{'Marker'},
1058             );
1059             }
1060             }
1061              
1062             =head2 get_policy_version(%params)
1063              
1064             Retrieves information about the specified version of the specified
1065             managed policy, including the policy document.
1066              
1067             =over
1068              
1069             =item PolicyArn (required)
1070              
1071             The Amazon Resource Name (ARN). ARNs are unique identifiers for AWS resources.
1072              
1073             =item VersionId (required)
1074              
1075             Identifies the policy version to retrieve.
1076              
1077             =back
1078              
1079             Returns L<Net::Amazon::IAM::PolicyVersion> on success or L<Net::Amazon::IAM::Error> on fail.
1080              
1081             =cut
1082              
1083             sub get_policy_version {
1084             my $self = shift;
1085              
1086             my %args = validate(@_, {
1087             PolicyArn => { type => SCALAR },
1088             VersionId => { type => SCALAR },
1089             });
1090              
1091             my $xml = $self->_sign(Action => 'GetPolicyVersion', %args);
1092              
1093             if ( grep { defined && length } $xml->{'Error'} ) {
1094             return $self->_parse_errors($xml);
1095             } else {
1096             my %result = %{$xml->{'GetPolicyVersionResult'}{'PolicyVersion'}};
1097             $result{'Document'} = decode_json(URI::Encode->new()->decode($result{'Document'}));
1098             return Net::Amazon::IAM::PolicyVersion->new(
1099             %result,
1100             );
1101             }
1102             }
1103              
1104             =head2 set_default_policy_version(%params)
1105              
1106             Sets the specified version of the specified policy as the policy's default (operative) version.
1107              
1108             =over
1109              
1110             =item PolicyArn (required)
1111              
1112             The Amazon Resource Name (ARN). ARNs are unique identifiers for AWS resources.
1113              
1114             =item VersionId (required)
1115              
1116             The version of the policy to set as the default (operative) version.
1117              
1118             =back
1119              
1120             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
1121              
1122             =cut
1123              
1124             sub set_default_policy_version {
1125             my $self = shift;
1126              
1127             my %args = validate(@_, {
1128             PolicyArn => { type => SCALAR },
1129             VersionId => { type => SCALAR },
1130             });
1131              
1132             my $xml = $self->_sign(Action => 'SetDefaultPolicyVersion', %args);
1133              
1134             if ( grep { defined && length } $xml->{'Error'} ) {
1135             return $self->_parse_errors($xml);
1136             } else {
1137             return 1;
1138             }
1139             }
1140              
1141             =head2 list_policy_versions(%params)
1142              
1143             Lists information about the versions of the specified managed policy, including the
1144             version that is set as the policy's default version.
1145              
1146             =over
1147              
1148             =item PolicyArn (required)
1149              
1150             The Amazon Resource Name (ARN). ARNs are unique identifiers for AWS resources.
1151              
1152             =item MaxItems (optional)
1153              
1154             Use this parameter only when paginating results to indicate the maximum number
1155             of policy versions you want in the response.
1156              
1157             =item Marker (optional)
1158              
1159             Use this parameter only when paginating results, and only in a subsequent request
1160             after you've received a response where the results are truncated. Set it to the value
1161             of the Marker element in the response you just received.
1162              
1163             =back
1164              
1165             Returns L<Net::Amazon::IAM::PolicyVersions> on success or L<Net::Amazon::IAM::Error> on fail.
1166              
1167             =cut
1168              
1169             sub list_policy_versions {
1170             my $self = shift;
1171              
1172             my %args = validate(@_, {
1173             PolicyArn => { type => SCALAR },
1174             MaxItems => { type => SCALAR, optional => 1 },
1175             Marker => { type => SCALAR, optional => 1 },
1176             });
1177              
1178             my $xml = $self->_sign(Action => 'ListPolicyVersions', %args);
1179              
1180             if ( grep { defined && length } $xml->{'Error'} ) {
1181             return $self->_parse_errors($xml);
1182             } else {
1183             my %result = %{$xml->{'ListPolicyVersionsResult'}};
1184             my $versions = $self->_parse_attributes('PolicyVersion', 'Versions', %result);
1185              
1186             return Net::Amazon::IAM::PolicyVersions->new(
1187             Policies => $versions,
1188             );
1189             }
1190             }
1191              
1192             =head2 create_policy_version(%params)
1193              
1194             Creates a new version of the specified managed policy. To update a managed policy,
1195             you create a new policy version. A managed policy can have up to five versions.
1196             If the policy has five versions, you must delete an existing version using DeletePolicyVersion
1197             before you create a new version.
1198              
1199             Optionally, you can set the new version as the policy's default version. The default version
1200             is the operative version; that is, the version that is in effect for the IAM users, groups,
1201             and roles that the policy is attached to.
1202              
1203             =over
1204              
1205             =item PolicyArn (required)
1206              
1207             The Amazon Resource Name (ARN). ARNs are unique identifiers for AWS resources.
1208              
1209             =item PolicyDocument (required)
1210              
1211             The policy document.
1212              
1213             =item SetAsDefault (optional)
1214              
1215             Specifies whether to set this version as the policy's default version.
1216              
1217             When this parameter is true, the new policy version becomes the operative
1218             version; that is, the version that is in effect for the IAM users, groups,
1219             and roles that the policy is attached to.
1220              
1221             =back
1222              
1223             Returns L<Net::Amazon::IAM::PolicyVersion> on success or L<Net::Amazon::IAM::Error> on fail.
1224              
1225             =cut
1226              
1227             sub create_policy_version {
1228             my $self = shift;
1229              
1230             my %args = validate(@_, {
1231             PolicyArn => { type => SCALAR },
1232             PolicyDocument => { type => HASHREF },
1233             SetAsDefault => { regex => qr/true|false/s, optional => 1 },
1234             });
1235              
1236             $args{'PolicyDocument'} = encode_json delete $args{'PolicyDocument'};
1237              
1238             my $xml = $self->_sign(Action => 'CreatePolicyVersion', %args);
1239              
1240             if ( grep { defined && length } $xml->{'Error'} ) {
1241             return $self->_parse_errors($xml);
1242             } else {
1243             return Net::Amazon::IAM::PolicyVersion->new(
1244             $xml->{'CreatePolicyVersionResult'}{'PolicyVersion'},
1245             );
1246             }
1247             }
1248              
1249             =head2 delete_policy_version(%params)
1250              
1251             =over
1252              
1253             =item PolicyArn (required)
1254              
1255             The Amazon Resource Name (ARN). ARNs are unique identifiers for AWS resources.
1256              
1257             =item VersionId (required)
1258              
1259             The policy version to delete.
1260              
1261             =back
1262              
1263             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
1264              
1265             =cut
1266              
1267             sub delete_policy_version {
1268             my $self = shift;
1269              
1270             my %args = validate(@_, {
1271             PolicyArn => { type => SCALAR },
1272             VersionId => { type => SCALAR },
1273             });
1274              
1275             my $xml = $self->_sign(Action => 'DeletePolicyVersion', %args);
1276              
1277             if ( grep { defined && length } $xml->{'Error'} ) {
1278             return $self->_parse_errors($xml);
1279             } else {
1280             return 1;
1281             }
1282             }
1283              
1284             =head2 put_user_policy(%params)
1285              
1286             Adds (or updates) an inline policy document that is embedded in the specified user.
1287              
1288             =over
1289              
1290             =item PolicyDocument (required)
1291              
1292             The policy document. Must be HashRef.
1293              
1294             =item PolicyName (required)
1295              
1296             The name of the policy document.
1297              
1298             =item UserName (required)
1299              
1300             The name of the user to associate the policy with.
1301              
1302             =back
1303              
1304             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
1305              
1306             =cut
1307              
1308             sub put_user_policy {
1309             my $self = shift;
1310              
1311             my %args = validate(@_, {
1312             PolicyDocument => { type => HASHREF },
1313             PolicyName => { type => SCALAR },
1314             UserName => { type => SCALAR },
1315             });
1316              
1317             $args{'PolicyDocument'} = encode_json delete $args{'PolicyDocument'};
1318              
1319             my $xml = $self->_sign(Action => 'PutUserPolicy', %args);
1320              
1321             if ( grep { defined && length } $xml->{'Error'} ) {
1322             return $self->_parse_errors($xml);
1323             } else {
1324             return 1;
1325             }
1326             }
1327              
1328             =head2 get_user_policy(%params)
1329              
1330             Retrieves the specified inline policy document that is embedded in the specified user.
1331              
1332             =over
1333              
1334             =item PolicyName (required)
1335              
1336             The name of the policy document to get.
1337              
1338             =item UserName (required)
1339              
1340             The name of the user who the policy is associated with.
1341              
1342             =back
1343              
1344             Returns L<Net::Amazon::IAM::UserPolicy> object on success or L<Net::Amazon::IAM::Error> on fail.
1345              
1346             =cut
1347              
1348             sub get_user_policy {
1349             my $self = shift;
1350              
1351             my %args = validate(@_, {
1352             PolicyName => { type => SCALAR },
1353             UserName => { type => SCALAR },
1354             });
1355              
1356             my $xml = $self->_sign(Action => 'GetUserPolicy', %args);
1357              
1358             if ( grep { defined && length } $xml->{'Error'} ) {
1359             return $self->_parse_errors($xml);
1360             } else {
1361             my $user_policy = Net::Amazon::IAM::UserPolicy->new(
1362             $xml->{'GetUserPolicyResult'}
1363             );
1364             $user_policy->{'PolicyDocument'} = decode_json(URI::Encode->new()->decode($user_policy->PolicyDocument));
1365             return $user_policy;
1366             }
1367             }
1368              
1369             =head2 delete_user_policy(%params)
1370              
1371             Deletes the specified inline policy that is embedded in the specified user.
1372              
1373             =over
1374              
1375             =item PolicyName (required)
1376              
1377             The name identifying the policy document to delete.
1378              
1379             =item UserName (required)
1380              
1381             The name (friendly name, not ARN) identifying the user that the policy is embedded in.
1382              
1383             =back
1384              
1385             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
1386              
1387             =cut
1388              
1389             sub delete_user_policy {
1390             my $self = shift;
1391              
1392             my %args = validate(@_, {
1393             PolicyName => { type => SCALAR },
1394             UserName => { type => SCALAR },
1395             });
1396              
1397             my $xml = $self->_sign(Action => 'DeleteUserPolicy', %args);
1398              
1399             if ( grep { defined && length } $xml->{'Error'} ) {
1400             return $self->_parse_errors($xml);
1401             } else {
1402             return 1;
1403             }
1404             }
1405              
1406             =head2 list_user_policies(%params)
1407              
1408             Lists the names of the inline policies embedded in the specified user.
1409              
1410             =over
1411              
1412             =item UserName (required)
1413              
1414             The name of the user to list policies for.
1415              
1416             =back
1417              
1418             When found one or more policies, this method will return ArrayRef with policy names.
1419             Once no policies found, will return undef.
1420             L<Net::Amazon::IAM::Error> will be returned on error.
1421              
1422             =cut
1423              
1424             sub list_user_policies {
1425             my $self = shift;
1426              
1427             my %args = validate(@_, {
1428             UserName => { type => SCALAR },
1429             Marker => { type => SCALAR, optional => 1 },
1430             MaxItems => { type => SCALAR, optional => 1 },
1431             });
1432              
1433             my $xml = $self->_sign(Action => 'ListUserPolicies', %args);
1434              
1435             if ( grep { defined && length } $xml->{'Error'} ) {
1436             return $self->_parse_errors($xml);
1437             } else {
1438             my $policies;
1439              
1440             my %result = %{$xml->{'ListUserPoliciesResult'}};
1441              
1442             if ( grep { defined && length } $result{'PolicyNames'} ) {
1443             if(ref($result{'PolicyNames'}{'member'}) eq 'ARRAY') {
1444             $policies = $result{'PolicyNames'}{'member'};
1445             }else{
1446             push @$policies, $result{'PolicyNames'}{'member'};
1447             }
1448             } else {
1449             $policies = undef;
1450             }
1451              
1452             return $policies;
1453             }
1454             }
1455              
1456             =head2 create_access_key(%params)
1457              
1458             Creates a new AWS secret access key and corresponding AWS access key ID for the specified user.
1459             The default status for new keys is Active.
1460             If you do not specify a user name, IAM determines the user name implicitly based on the AWS access
1461             key ID signing the request. Because this action works for access keys under the AWS account, you can use
1462             this action to manage root credentials even if the AWS account has no associated users.
1463              
1464             B<Important>:
1465              
1466             To ensure the security of your AWS account, the secret access key is accessible only during
1467             key and user creation. You must save the key (for example, in a text file) if you want to be
1468             able to access it again. If a secret key is lost, you can delete the access keys for the associated
1469             user and then create new keys.
1470              
1471             =over
1472              
1473             =item UserName (optional)
1474              
1475             The user name that the new key will belong to.
1476              
1477             =back
1478              
1479             Returns L<Net::Amazon::IAM::AccessKey> object on success or L<Net::Amazon::IAM::Error> on fail.
1480              
1481             =cut
1482              
1483             sub create_access_key {
1484             my $self = shift;
1485              
1486             my %args = validate(@_, {
1487             UserName => { type => SCALAR, optional => 1 },
1488             });
1489              
1490             my $xml = $self->_sign(Action => 'CreateAccessKey', %args);
1491              
1492             if ( grep { defined && length } $xml->{'Error'} ) {
1493             return $self->_parse_errors($xml);
1494             } else {
1495             return Net::Amazon::IAM::AccessKey->new(
1496             $xml->{'CreateAccessKeyResult'}{'AccessKey'},
1497             );
1498             }
1499             }
1500              
1501             =head2 delete_access_key(%params)
1502              
1503             Deletes the access key associated with the specified user.
1504              
1505             If you do not specify a user name, IAM determines the user name implicitly based
1506             on the AWS access key ID signing the request. Because this action works for access
1507             keys under the AWS account, you can use this action to manage root credentials even
1508             if the AWS account has no associated users.
1509              
1510             =over
1511              
1512             =item AccessKeyId (required)
1513              
1514             The access key ID for the access key ID and secret access key you want to delete.
1515              
1516             =item UserName (optional)
1517              
1518             The name of the user whose key you want to delete.
1519              
1520             =back
1521              
1522             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
1523              
1524             =cut
1525              
1526             sub delete_access_key {
1527             my $self = shift;
1528              
1529             my %args = validate(@_, {
1530             AccessKeyId => { type => SCALAR },
1531             UserName => { type => SCALAR, optional => 1 },
1532             });
1533              
1534             my $xml = $self->_sign(Action => 'DeleteAccessKey', %args);
1535              
1536             if ( grep { defined && length } $xml->{'Error'} ) {
1537             return $self->_parse_errors($xml);
1538             } else {
1539             return 1;
1540             }
1541             }
1542              
1543             =head2 update_access_key(%params)
1544              
1545             Changes the status of the specified access key from Active to Inactive, or vice versa.
1546             This action can be used to disable a user's key as part of a key rotation work flow.
1547              
1548             If the UserName field is not specified, the UserName is determined implicitly based
1549             on the AWS access key ID used to sign the request. Because this action works for access
1550             keys under the AWS account, you can use this action to manage root credentials even if
1551             the AWS account has no associated users.
1552              
1553             =over
1554              
1555             =item AccessKeyId (required)
1556              
1557             The access key ID of the secret access key you want to update.
1558              
1559             =item Status (required)
1560              
1561             The status you want to assign to the secret access key.
1562             Active means the key can be used for API calls to AWS, while Inactive
1563             means the key cannot be used.
1564              
1565             =item UserName (optional)
1566              
1567             The name of the user whose key you want to update.
1568              
1569             =back
1570              
1571             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
1572              
1573             =cut
1574              
1575             sub update_access_key {
1576             my $self = shift;
1577              
1578             my %args = validate(@_, {
1579             AccessKeyId => { type => SCALAR },
1580             Status => { regex => qr/Active|Inactive/ },
1581             UserName => { type => SCALAR, optional => 1 },
1582             });
1583              
1584             my $xml = $self->_sign(Action => 'UpdateAccessKey', %args);
1585              
1586             if ( grep { defined && length } $xml->{'Error'} ) {
1587             return $self->_parse_errors($xml);
1588             } else {
1589             return 1;
1590             }
1591             }
1592              
1593             =head2 list_access_keys(%params)
1594              
1595             Returns information about the access key IDs associated with the specified user.
1596             If the UserName field is not specified, the UserName is determined implicitly based on the AWS access
1597             key ID used to sign the request. Because this action works for access keys under the AWS account,
1598             you can use this action to manage root credentials even if the AWS account has no associated users.
1599              
1600             =over
1601              
1602             =item UserName (optional)
1603              
1604             The name of the user.
1605              
1606             =back
1607              
1608             Returns Net::Amazon::IAM::AccessKeysList on success.
1609             If specified user has no keys, "Keys" attribute of L<Net::Amazon::IAM::AccessKeysList> object
1610             will be just empty array.
1611             Returns L<Net::Amazon::IAM::Error> on fail.
1612              
1613             =cut
1614              
1615             sub list_access_keys {
1616             my $self = shift;
1617              
1618             my %args = validate(@_, {
1619             UserName => { type => SCALAR, optional => 1 },
1620             });
1621              
1622             my $xml = $self->_sign(Action => 'ListAccessKeys', %args);
1623              
1624             if ( grep { defined && length } $xml->{'Error'} ) {
1625             return $self->_parse_errors($xml);
1626             } else {
1627             my %result = %{$xml->{'ListAccessKeysResult'}};
1628             my $keys = $self->_parse_attributes('AccessKeyMetadata', 'AccessKeyMetadata', %result);
1629              
1630             return Net::Amazon::IAM::AccessKeysList->new(
1631             Keys => $keys,
1632             );
1633             }
1634             }
1635              
1636             =head2 create_role(%params)
1637              
1638             Creates a new role for your AWS account.
1639              
1640             The example policy grants permission to an EC2 instance to assume the role.
1641             {
1642             "Version": "2012-10-17",
1643             "Statement": [{
1644             "Effect": "Allow",
1645             "Principal": {
1646             "Service": ["ec2.amazonaws.com"]
1647             },
1648             "Action": ["sts:AssumeRole"]
1649             }]
1650             }
1651              
1652             =over
1653              
1654             =item AssumeRolePolicyDocument (required)
1655              
1656             The policy that grants an entity permission to assume the role.
1657              
1658             =item RoleName (required)
1659              
1660             The name of the role to create.
1661              
1662             =item Path (optional)
1663              
1664             The path to the role.
1665              
1666             =back
1667              
1668             Returns L<Net::Amazon::IAM::Role> object on success or L<Net::Amazon::IAM::Error> on fail.
1669              
1670             =cut
1671              
1672             sub create_role {
1673             my $self = shift;
1674              
1675             my %args = validate(@_, {
1676             AssumeRolePolicyDocument => { type => HASHREF },
1677             RoleName => { type => SCALAR },
1678             Path => { type => SCALAR, optional => 1 },
1679             });
1680              
1681             $args{'AssumeRolePolicyDocument'} = encode_json delete $args{'AssumeRolePolicyDocument'};
1682              
1683             my $xml = $self->_sign(Action => 'CreateRole', %args);
1684              
1685             if ( grep { defined && length } $xml->{'Error'} ) {
1686             return $self->_parse_errors($xml);
1687             } else {
1688             return Net::Amazon::IAM::Role->new(
1689             $xml->{'CreateRoleResult'}{'Role'},
1690             );
1691             }
1692             }
1693              
1694             =head2 get_role(%params)
1695              
1696             Retrieves information about the specified role.
1697              
1698             =over
1699              
1700             =item RoleName (required)
1701              
1702             The name of the role to get information about.
1703              
1704             =back
1705              
1706             Returns L<Net::Amazon::IAM::Role> object on success or L<Net::Amazon::IAM::Error> on fail.
1707              
1708             =cut
1709              
1710             sub get_role {
1711             my $self = shift;
1712              
1713             my %args = validate(@_, {
1714             RoleName => { type => SCALAR },
1715             });
1716              
1717             my $xml = $self->_sign(Action => 'GetRole', %args);
1718              
1719             if( grep { defined && length } $xml->{'Error'} ) {
1720             return $self->_parse_errors($xml);
1721             }else{
1722             my $role = Net::Amazon::IAM::Role->new(
1723             $xml->{'GetRoleResult'}{'Role'},
1724             );
1725              
1726             $role->{'AssumeRolePolicyDocument'} = decode_json(
1727             URI::Encode->new()->decode($role->AssumeRolePolicyDocument)
1728             );
1729              
1730             return $role;
1731             }
1732             }
1733              
1734             =head2 list_roles(%params)
1735              
1736             Retrieves information about the specified role.
1737              
1738             =over
1739              
1740             =item Marker (optional)
1741              
1742             Use this parameter only when paginating results, and only in a subsequent
1743             request after you've received a response where the results are truncated.
1744             Set it to the value of the Marker element in the response you just received.
1745              
1746             =item MaxItems (optional)
1747              
1748             Use this parameter only when paginating results to indicate the maximum number
1749             of roles you want in the response. If there are additional roles beyond the maximum
1750             you specify, the IsTruncated response element is true. This parameter is optional.
1751             If you do not include it, it defaults to 100.
1752              
1753             =item PathPrefix (optional)
1754              
1755             The path prefix for filtering the results. For example, the prefix /application_abc/component_xyz/
1756             gets all roles whose path starts with /application_abc/component_xyz/.
1757              
1758             This parameter is optional. If it is not included, it defaults to a slash (/), listing all roles.
1759              
1760             =back
1761              
1762             Returns L<Net::Amazon::IAM::Roles> object on success or L<Net::Amazon::IAM::Error> on fail.
1763              
1764             =cut
1765              
1766             sub list_roles {
1767             my $self = shift;
1768              
1769             my %args = validate(@_, {
1770             Marker => { type => SCALAR, optional => 1 },
1771             MaxItems => { type => SCALAR, optional => 1 },
1772             PathPrefix => { type => SCALAR, optional => 1 },
1773             });
1774              
1775             my $xml = $self->_sign(Action => 'ListRoles', %args);
1776              
1777             if ( grep { defined && length } $xml->{'Error'} ) {
1778             return $self->_parse_errors($xml);
1779             } else {
1780             my %result = %{$xml->{'ListRolesResult'}};
1781             my $roles = $self->_parse_attributes('Role', 'Roles', %result);
1782              
1783             return Net::Amazon::IAM::Roles->new(
1784             Roles => $roles,
1785             Marker => $result{'Marker'},
1786             IsTruncated => $result{'IsTruncated'},
1787             );
1788             }
1789             }
1790              
1791             =head2 delete_role(%params)
1792              
1793             Deletes the specified role. The role must not have any policies attached.
1794              
1795             B<Important>:
1796              
1797             Make sure you do not have any Amazon EC2 instances running with the role you are about to delete.
1798             Deleting a role or instance profile that is associated with a running instance will break any
1799             applications running on the instance.
1800              
1801             =over
1802              
1803             =item RoleName (required)
1804              
1805             The name of the role to delete.
1806              
1807             =back
1808              
1809             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
1810              
1811             =cut
1812              
1813             sub delete_role {
1814             my $self = shift;
1815              
1816             my %args = validate(@_, {
1817             RoleName => { type => SCALAR },
1818             });
1819              
1820             my $xml = $self->_sign(Action => 'DeleteRole', %args);
1821              
1822             if ( grep { defined && length } $xml->{'Error'} ) {
1823             return $self->_parse_errors($xml);
1824             } else {
1825             return 1;
1826             }
1827             }
1828              
1829             =head2 put_role_policy(%params)
1830              
1831             Adds (or updates) an inline policy document that is embedded in the specified role.
1832              
1833             =over
1834              
1835             =item PolicyDocument (required)
1836              
1837             The policy document.
1838              
1839             =item PolicyName (required)
1840              
1841             The name of the policy document.
1842              
1843             =item RoleName (required)
1844              
1845             The name of the role to associate the policy with.
1846              
1847             =back
1848              
1849             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
1850              
1851             =cut
1852              
1853             sub put_role_policy {
1854             my $self = shift;
1855              
1856             my %args = validate(@_, {
1857             PolicyDocument => { type => HASHREF },
1858             PolicyName => { type => SCALAR },
1859             RoleName => { type => SCALAR },
1860             });
1861              
1862             $args{'PolicyDocument'} = encode_json delete $args{'PolicyDocument'};
1863              
1864             my $xml = $self->_sign(Action => 'PutRolePolicy', %args);
1865              
1866             if ( grep { defined && length } $xml->{'Error'} ) {
1867             return $self->_parse_errors($xml);
1868             } else {
1869             return 1;
1870             }
1871             }
1872              
1873             =head2 create_virtual_MFA_device(%params)
1874              
1875             Creates a new virtual MFA device for the AWS account.
1876             After creating the virtual MFA, use EnableMFADevice to
1877             attach the MFA device to an IAM user.
1878              
1879             B<Important>:
1880              
1881             The seed information contained in the QR code and the Base32 string
1882             should be treated like any other secret access information, such as
1883             your AWS access keys or your passwords. After you provision your virtual
1884             device, you should ensure that the information is destroyed following
1885             secure procedures.
1886              
1887             =over
1888              
1889             =item VirtualMFADeviceName (required)
1890              
1891             The name of the virtual MFA device. Use with path to uniquely identify a virtual MFA device.
1892              
1893             =item Path (required)
1894              
1895             The path for the virtual MFA device.
1896              
1897             =back
1898              
1899             Returns L<Net::Amazon::IAM::VirtualMFADevice> object on success or L<Net::Amazon::IAM::Error> on fail.
1900              
1901             B<This method wasn't tested>
1902              
1903             =cut
1904              
1905             sub create_virtual_MFA_device {
1906             my $self = shift;
1907              
1908             my %args = validate(@_, {
1909             VirtualMFADeviceName => { type => SCALAR },
1910             Path => { type => SCALAR, optional => 1 },
1911             });
1912              
1913             my $xml = $self->_sign(Action => 'CreateVirtualMFADevice', %args);
1914              
1915             if ( grep { defined && length } $xml->{'Error'} ) {
1916             return $self->_parse_errors($xml);
1917             } else {
1918             return Net::Amazon::IAM::VirtualMFADevice->new(
1919             $xml->{'CreateVirtualMFADeviceResult'}{'VirtualMFADevice'},
1920             );
1921             }
1922             }
1923              
1924             =head2 delete_virtual_MFA_device(%params)
1925              
1926             Deletes a virtual MFA device.
1927              
1928             B<Note>:
1929              
1930             You must deactivate a user's virtual MFA device before you can delete it.
1931              
1932             =over
1933              
1934             =item SerialNumber (required)
1935              
1936             The serial number that uniquely identifies the MFA device.
1937             For virtual MFA devices, the serial number is the same as the ARN.
1938              
1939             =back
1940              
1941             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
1942              
1943             B<This method wasn't tested>
1944              
1945             =cut
1946              
1947             sub delete_virtual_MFA_device {
1948             my $self = shift;
1949              
1950             my %args = validate(@_, {
1951             SerialNumber => { type => SCALAR },
1952             });
1953              
1954             my $xml = $self->_sign(Action => 'DeleteVirtualMFADevice', %args);
1955              
1956             if ( grep { defined && length } $xml->{'Error'} ) {
1957             return $self->_parse_errors($xml);
1958             } else {
1959             return 1;
1960             }
1961             }
1962              
1963             =head2 list_virtual_MFA_devices(%params)
1964              
1965             Lists the virtual MFA devices under the AWS account by assignment status.
1966              
1967             =over
1968              
1969             =item Marker (optional)
1970              
1971             Use this parameter only when paginating results, and only in a subsequent
1972             request after you've received a response where the results are truncated.
1973             Set it to the value of the Marker element in the response you just received.
1974              
1975             =item MaxItems (optional)
1976              
1977             Use this parameter only when paginating results to indicate the maximum number
1978             of VirtualMFADevices you want in the response. If there are additional devices beyond the maximum
1979             you specify, the IsTruncated response element is true. This parameter is optional.
1980             If you do not include it, it defaults to 100.
1981              
1982             =item AssignmentStatus (optional)
1983              
1984             The status (unassigned or assigned) of the devices to list.
1985             If you do not specify an AssignmentStatus, the action defaults to Any
1986             which lists both assigned and unassigned virtual MFA devices.
1987              
1988             Valid Values: Assigned | Unassigned | Any
1989              
1990             =back
1991              
1992             Returns L<Net::Amazon::IAM::MFADevices> object on success or L<Net::Amazon::IAM::Error> on fail.
1993              
1994             =cut
1995              
1996             sub list_virtual_MFA_devices {
1997             my $self = shift;
1998              
1999             my %args = validate(@_, {
2000             AssignmentStatus => { regex => qr/Assigned|Unassigned|Any/, optional => 1 },
2001             Marker => { type => SCALAR, optional => 1 },
2002             MaxItems => { type => SCALAR, optional => 1 },
2003             });
2004              
2005             my $xml = $self->_sign(Action => 'ListVirtualMFADevices', %args);
2006              
2007             if ( grep { defined && length } $xml->{'Error'} ) {
2008             return $self->_parse_errors($xml);
2009             } else {
2010             my $devices;
2011              
2012             my %result = %{$xml->{'ListVirtualMFADevicesResult'}};
2013              
2014             if ( grep { defined && length } $result{'MFADevices'} ) {
2015             if(ref($result{'VirtualMFADevices'}{'member'}) eq 'ARRAY') {
2016             for my $device(@{$result{'VirtualMFADevices'}{'member'}}) {
2017             my $d = Net::Amazon::IAM::VirtualMFADevice->new(
2018             $device,
2019             );
2020             push @$devices, $d;
2021             }
2022             }else{
2023             my $d = Net::Amazon::IAM::VirtualMFADevice->new(
2024             $result{'VirtualMFADevices'}{'member'},
2025             );
2026             push @$devices, $d;
2027             }
2028             }else{
2029             $devices = [];
2030             }
2031              
2032             return Net::Amazon::IAM::VirtualMFADevices->new(
2033             VirtualMFADevices => $devices,
2034             Marker => $result{'Marker'},
2035             IsTruncated => $result{'IsTruncated'},
2036             );
2037             }
2038             }
2039              
2040             =head2 enable_MFA_device(%params)
2041              
2042             Enables the specified MFA device and associates it with the specified user name.
2043             When enabled, the MFA device is required for every subsequent login by the user
2044             name associated with the device.
2045              
2046             =over
2047              
2048             =item AuthenticationCode1 (required)
2049              
2050             An authentication code emitted by the device.
2051              
2052             =item AuthenticationCode2 (required)
2053              
2054             A subsequent authentication code emitted by the device.
2055              
2056             =item SerialNumber (required)
2057              
2058             The serial number that uniquely identifies the MFA device.
2059             For virtual MFA devices, the serial number is the device ARN.
2060              
2061             =item UserName (required)
2062              
2063             The name of the user for whom you want to enable the MFA device.
2064              
2065             =back
2066              
2067             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
2068              
2069             B<This method wasn't tested>
2070              
2071             =cut
2072              
2073             sub enable_MFA_device {
2074             my $self = shift;
2075              
2076             my %args = validate(@_, {
2077             AuthenticationCode1 => { type => SCALAR },
2078             AuthenticationCode2 => { type => SCALAR },
2079             SerialNumber => { type => SCALAR },
2080             UserName => { type => SCALAR },
2081             });
2082              
2083             my $xml = $self->_sign(Action => 'EnableMFADevice', %args);
2084              
2085             if ( grep { defined && length } $xml->{'Error'} ) {
2086             return $self->_parse_errors($xml);
2087             } else {
2088             return 1;
2089             }
2090             }
2091              
2092             =head2 deactivate_MFA_device(%params)
2093              
2094             Enables the specified MFA device and associates it with the specified user name.
2095             When enabled, the MFA device is required for every subsequent login by the user
2096             name associated with the device.
2097              
2098             =over
2099              
2100             =item SerialNumber (required)
2101              
2102             The serial number that uniquely identifies the MFA device.
2103             For virtual MFA devices, the serial number is the device ARN.
2104              
2105             =item UserName (required)
2106              
2107             The name of the user whose MFA device you want to deactivate.
2108              
2109             =back
2110              
2111             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
2112              
2113             B<This method wasn't tested>
2114              
2115             =cut
2116              
2117             sub deactivate_MFA_device {
2118             my $self = shift;
2119              
2120             my %args = validate(@_, {
2121             SerialNumber => { type => SCALAR },
2122             UserName => { type => SCALAR },
2123             });
2124              
2125             my $xml = $self->_sign(Action => 'DeactivateMFADevice', %args);
2126              
2127             if ( grep { defined && length } $xml->{'Error'} ) {
2128             return $self->_parse_errors($xml);
2129             } else {
2130             return 1;
2131             }
2132             }
2133              
2134             =head2 list_MFA_devices(%params)
2135              
2136             Retrieves information about the specified role.
2137              
2138             =over
2139              
2140             =item Marker (optional)
2141              
2142             Use this parameter only when paginating results, and only in a subsequent
2143             request after you've received a response where the results are truncated.
2144             Set it to the value of the Marker element in the response you just received.
2145              
2146             =item MaxItems (optional)
2147              
2148             Use this parameter only when paginating results to indicate the maximum number
2149             of MFADevices you want in the response. If there are additional devices beyond the maximum
2150             you specify, the IsTruncated response element is true. This parameter is optional.
2151             If you do not include it, it defaults to 100.
2152              
2153             =item UserName (optional)
2154              
2155             The name of the user whose MFA devices you want to list.
2156              
2157             =back
2158              
2159             Returns L<Net::Amazon::IAM::MFADevices> object on success or L<Net::Amazon::IAM::Error> on fail.
2160              
2161             =cut
2162              
2163             sub list_MFA_devices {
2164             my $self = shift;
2165              
2166             my %args = validate(@_, {
2167             Marker => { type => SCALAR, optional => 1 },
2168             MaxItems => { type => SCALAR, optional => 1 },
2169             UserName => { type => SCALAR, optional => 1 },
2170             });
2171              
2172             my $xml = $self->_sign(Action => 'ListMFADevices', %args);
2173              
2174             if ( grep { defined && length } $xml->{'Error'} ) {
2175             return $self->_parse_errors($xml);
2176             } else {
2177             my $devices;
2178              
2179             my %result = %{$xml->{'ListMFADevicesResult'}};
2180              
2181             if ( grep { defined && length } $result{'MFADevices'} ) {
2182             if(ref($result{'MFADevices'}{'member'}) eq 'ARRAY') {
2183             for my $device(@{$result{'MFADevices'}{'member'}}) {
2184             my $d = Net::Amazon::IAM::MFADevice->new(
2185             $device,
2186             );
2187             push @$devices, $d;
2188             }
2189             }else{
2190             my $d = Net::Amazon::IAM::MFADevice->new(
2191             $result{'MFADevices'}{'member'},
2192             );
2193             push @$devices, $d;
2194             }
2195             }else{
2196             $devices = [];
2197             }
2198              
2199             return Net::Amazon::IAM::MFADevices->new(
2200             MFADevices => $devices,
2201             Marker => $result{'Marker'},
2202             IsTruncated => $result{'IsTruncated'},
2203             );
2204             }
2205             }
2206              
2207             =head2 create_instance_profile(%params)
2208              
2209             Creates a new instance profile.
2210              
2211             =over
2212              
2213             =item InstanceProfileName (required)
2214              
2215             The name of the instance profile to create.
2216              
2217             =item Path (optional)
2218              
2219             The path to the instance profile.
2220              
2221             =back
2222              
2223             Returns L<Net::Amazon::IAM::InstanceProfile> object on success or L<Net::Amazon::IAM::Error> on fail.
2224              
2225             =cut
2226              
2227              
2228             sub create_instance_profile {
2229             my $self = shift;
2230              
2231             my %args = validate(@_, {
2232             InstanceProfileName => { type => SCALAR },
2233             Path => { type => SCALAR, optional => 1 },
2234             });
2235              
2236             my $xml = $self->_sign(Action => 'CreateInstanceProfile', %args);
2237              
2238             if ( grep { defined && length } $xml->{'Error'} ) {
2239             return $self->_parse_errors($xml);
2240             } else {
2241             return Net::Amazon::IAM::InstanceProfile->new(
2242             $xml->{'CreateInstanceProfileResult'}{'InstanceProfile'},
2243             );
2244             }
2245             }
2246              
2247             =head2 get_instance_profile(%params)
2248              
2249             Retrieves information about the specified instance profile,
2250             including the instance profile's path, GUID, ARN, and role.
2251              
2252             =over
2253              
2254             =item InstanceProfileName (required)
2255              
2256             The name of the instance profile to get information about.
2257              
2258             =back
2259              
2260             Returns L<Net::Amazon::IAM::InstanceProfile> object on success or L<Net::Amazon::IAM::Error> on fail.
2261              
2262             =cut
2263              
2264             sub get_instance_profile {
2265             my $self = shift;
2266              
2267             my %args = validate(@_, {
2268             InstanceProfileName => { type => SCALAR },
2269             });
2270              
2271             my $xml = $self->_sign(Action => 'GetInstanceProfile', %args);
2272              
2273             if ( grep { defined && length } $xml->{'Error'} ) {
2274             return $self->_parse_errors($xml);
2275             } else {
2276             my %result = %{$xml->{'GetInstanceProfileResult'}{'InstanceProfile'}};
2277             my $roles = $self->_parse_attributes('Role', 'Roles', %result);
2278              
2279             my $roles_obj = Net::Amazon::IAM::Roles->new(
2280             Roles => $roles,
2281             );
2282              
2283             return Net::Amazon::IAM::InstanceProfile->new(
2284             Arn => $result{'Arn'},
2285             CreateDate => $result{'CreateDate'},
2286             InstanceProfileId => $result{'InstanceProfileId'},
2287             InstanceProfileName => $result{'InstanceProfileName'},
2288             Path => $result{'Path'},
2289             Roles => $roles_obj,
2290             );
2291             }
2292             }
2293              
2294             =head2 list_instance_profiles(%params)
2295              
2296             Lists the instance profiles that have the specified path prefix.
2297              
2298             =over
2299              
2300             =item Marker (optional)
2301              
2302             Use this parameter only when paginating results, and only in a subsequent
2303             request after you've received a response where the results are truncated.
2304             Set it to the value of the Marker element in the response you just received.
2305              
2306             =item MaxItems (optional)
2307              
2308             Use this parameter only when paginating results to indicate the maximum number
2309             of instance profiles you want in the response. If there are additional instance
2310             profiles beyond the maximum you specify, the IsTruncated response element is true.
2311             This parameter is optional. If you do not include it, it defaults to 100.
2312              
2313             =item PathPrefix (optional)
2314              
2315             The path prefix for filtering the results. For example, the prefix
2316             /application_abc/component_xyz/ gets all instance profiles whose path
2317             starts with /application_abc/component_xyz/.
2318              
2319             =back
2320              
2321             Returns L<Net::Amazon::IAM::InstanceProfiles> object on success or L<Net::Amazon::IAM::Error> on fail.
2322              
2323             =cut
2324              
2325             sub list_instance_profiles {
2326             my $self = shift;
2327              
2328             my %args = validate(@_, {
2329             Marker => { type => SCALAR, optional => 1 },
2330             MaxItems => { type => SCALAR, optional => 1 },
2331             PathPrefix => { type => SCALAR, optional => 1 },
2332             });
2333              
2334             my $xml = $self->_sign(Action => 'ListInstanceProfiles', %args);
2335              
2336             if ( grep { defined && length } $xml->{'Error'} ) {
2337             return $self->_parse_errors($xml);
2338             } else {
2339             my %result = %{$xml->{'ListInstanceProfilesResult'}};
2340             my $instance_profiles = $self->_parse_attributes('InstanceProfile', 'InstanceProfiles', %result);
2341              
2342             for my $profile (@{$instance_profiles}) {
2343             my %roles;
2344             $roles{'Roles'} = $profile->{'Roles'};
2345             my $roles = $self->_parse_attributes('Role', 'Roles', %roles);
2346              
2347             my $roles_obj = Net::Amazon::IAM::Roles->new(
2348             Roles => $roles,
2349             );
2350              
2351             $profile->{'Roles'} = $roles_obj;
2352             }
2353              
2354             return Net::Amazon::IAM::InstanceProfiles->new(
2355             InstanceProfiles => $instance_profiles,
2356             Marker => $result{'Marker'},
2357             IsTruncated => $result{'IsTruncated'},
2358             );
2359             }
2360             }
2361              
2362             =head2 delete_instance_profile(%params)
2363              
2364             Deletes the specified instance profile. The instance profile must not have an associated role.
2365              
2366             =over
2367              
2368             =item InstanceProfileName (required)
2369              
2370             The name of the instance profile to delete.
2371              
2372             =back
2373              
2374             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
2375              
2376             =cut
2377              
2378             sub delete_instance_profile {
2379             my $self = shift;
2380              
2381             my %args = validate(@_, {
2382             InstanceProfileName => { type => SCALAR },
2383             });
2384              
2385             my $xml = $self->_sign(Action => 'DeleteInstanceProfile', %args);
2386              
2387             if ( grep { defined && length } $xml->{'Error'} ) {
2388             return $self->_parse_errors($xml);
2389             } else {
2390             return 1;
2391             }
2392             }
2393              
2394             =head2 add_role_to_instance_profile(%params)
2395              
2396             Adds the specified role to the specified instance profile.
2397              
2398             =over
2399              
2400             =item InstanceProfileName (required)
2401              
2402             The name of the instance profile to update.
2403              
2404             =item RoleName (required)
2405              
2406             The name of the role to add.
2407              
2408             =back
2409              
2410             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
2411              
2412             =cut
2413              
2414             sub add_role_to_instance_profile {
2415             my $self = shift;
2416              
2417             my %args = validate(@_, {
2418             InstanceProfileName => { type => SCALAR },
2419             RoleName => { type => SCALAR },
2420             });
2421              
2422             my $xml = $self->_sign(Action => 'AddRoleToInstanceProfile', %args);
2423              
2424             if ( grep { defined && length } $xml->{'Error'} ) {
2425             return $self->_parse_errors($xml);
2426             } else {
2427             return 1;
2428             }
2429             }
2430              
2431             =head2 remove_role_from_instance_profile(%params)
2432              
2433             Removes the specified role from the specified instance profile.
2434              
2435             B<Important>:
2436              
2437             Make sure you do not have any Amazon EC2 instances running with the role
2438             you are about to remove from the instance profile. Removing a role from an
2439             instance profile that is associated with a running instance will break any
2440             applications running on the instance.
2441              
2442             =over
2443              
2444             =item InstanceProfileName (required)
2445              
2446             The name of the instance profile to update.
2447              
2448             =item RoleName (required)
2449              
2450             The name of the role to remove.
2451              
2452             =back
2453              
2454             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
2455              
2456             =cut
2457              
2458             sub remove_role_from_instance_profile {
2459             my $self = shift;
2460              
2461             my %args = validate(@_, {
2462             InstanceProfileName => { type => SCALAR },
2463             RoleName => { type => SCALAR },
2464             });
2465              
2466             my $xml = $self->_sign(Action => 'RemoveRoleFromInstanceProfile', %args);
2467              
2468             if ( grep { defined && length } $xml->{'Error'} ) {
2469             return $self->_parse_errors($xml);
2470             } else {
2471             return 1;
2472             }
2473             }
2474              
2475             =head2 list_instance_profiles_for_role(%params)
2476              
2477             Lists the instance profiles that have the specified associated role.
2478              
2479             =over
2480              
2481             =item RoleName (required)
2482              
2483             The name of the role to list instance profiles for.
2484              
2485             =item MaxItems (optional)
2486              
2487             Use this parameter only when paginating results to indicate the maximum number of
2488             instance profiles you want in the response. If there are additional instance profiles
2489             beyond the maximum you specify, the IsTruncated response element is true. This parameter
2490             is optional. If you do not include it, it defaults to 100.
2491              
2492             =item Marker (optional)
2493              
2494             Use this parameter only when paginating results, and only in a subsequent request
2495             after you've received a response where the results are truncated. Set it to the
2496             value of the Marker element in the response you just received.
2497              
2498             =back
2499              
2500             Returns L<Net::Amazon::IAM::InstanceProfiles> object on success or L<Net::Amazon::IAM::Error> on fail.
2501              
2502             =cut
2503              
2504             sub list_instance_profiles_for_role {
2505             my $self = shift;
2506              
2507             my %args = validate(@_, {
2508             RoleName => { type => SCALAR },
2509             Marker => { type => SCALAR, optional => 1 },
2510             MaxItems => { type => SCALAR, optional => 1 },
2511             });
2512              
2513             my $xml = $self->_sign(Action => 'ListInstanceProfilesForRole', %args);
2514              
2515             if ( grep { defined && length } $xml->{'Error'} ) {
2516             return $self->_parse_errors($xml);
2517             } else {
2518             my %result = %{$xml->{'ListInstanceProfilesForRoleResult'}};
2519             my $instance_profiles = $self->_parse_attributes('InstanceProfile', 'InstanceProfiles', %result);
2520              
2521             for my $profile (@{$instance_profiles}) {
2522             my %roles;
2523             $roles{'Roles'} = $profile->{'Roles'};
2524             my $roles = $self->_parse_attributes('Role', 'Roles', %roles);
2525              
2526             my $roles_obj = Net::Amazon::IAM::Roles->new(
2527             Roles => $roles,
2528             );
2529              
2530             $profile->{'Roles'} = $roles_obj;
2531             }
2532              
2533             return Net::Amazon::IAM::InstanceProfiles->new(
2534             InstanceProfiles => $instance_profiles,
2535             Marker => $result{'Marker'},
2536             IsTruncated => $result{'IsTruncated'},
2537             );
2538             }
2539             }
2540              
2541             =head2 create_login_profile(%params)
2542              
2543             Lists the instance profiles that have the specified associated role.
2544              
2545             =over
2546              
2547             =item UserName (required)
2548              
2549             The name of the user to create a password for.
2550              
2551             =item Password (required)
2552              
2553             The new password for the user.
2554              
2555             =item PasswordResetRequired (optional)
2556              
2557             Specifies whether the user is required to set a new password on next sign-in.
2558              
2559             =back
2560              
2561             Returns L<Net::Amazon::IAM::LoginProfile> object on success or L<Net::Amazon::IAM::Error> on fail.
2562              
2563             =cut
2564              
2565             sub create_login_profile {
2566             my $self = shift;
2567              
2568             my %args = validate(@_, {
2569             Password => { type => SCALAR },
2570             UserName => { type => SCALAR },
2571             PasswordResetRequired => { type => SCALAR, optional => 1 },
2572             });
2573              
2574             my $xml = $self->_sign(Action => 'CreateLoginProfile', %args);
2575              
2576             if ( grep { defined && length } $xml->{'Error'} ) {
2577             return $self->_parse_errors($xml);
2578             } else {
2579             return Net::Amazon::IAM::LoginProfile->new(
2580             $xml->{'CreateLoginProfileResult'}{'LoginProfile'},
2581             );
2582             }
2583             }
2584              
2585             =head2 delete_login_profile(%params)
2586              
2587             Deletes the password for the specified user, which terminates the user's ability
2588             to access AWS services through the AWS Management Console.
2589              
2590             B<Important>:
2591             Deleting a user's password does not prevent a user from accessing IAM through
2592             the command line interface or the API. To prevent all user access you must also either
2593             make the access key inactive or delete it. For more information about making keys inactive
2594             or deleting them, see update_access_key and delete_access_key.
2595              
2596             =over
2597              
2598             =item UserName (required)
2599              
2600             The name of the user whose password you want to delete.
2601              
2602             =back
2603              
2604             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
2605              
2606             =cut
2607              
2608             sub delete_login_profile {
2609             my $self = shift;
2610              
2611             my %args = validate(@_, {
2612             UserName => { type => SCALAR },
2613             });
2614              
2615             my $xml = $self->_sign(Action => 'DeleteLoginProfile', %args);
2616              
2617             if ( grep { defined && length } $xml->{'Error'} ) {
2618             return $self->_parse_errors($xml);
2619             } else {
2620             return 1;
2621             }
2622             }
2623              
2624             =head2 get_login_profile(%params)
2625              
2626             Retrieves the user name and password-creation date for the specified user.
2627             If the user has not been assigned a password, the action returns a 404 (NoSuchEntity) error.
2628              
2629             =over
2630              
2631             =item UserName (required)
2632              
2633             The name of the user whose login profile you want to retrieve.
2634              
2635             =back
2636              
2637             Returns L<Net::Amazon::IAM::LoginProfile> object on success or L<Net::Amazon::IAM::Error> on fail.
2638              
2639             =cut
2640              
2641             sub get_login_profile {
2642             my $self = shift;
2643              
2644             my %args = validate(@_, {
2645             UserName => { type => SCALAR },
2646             });
2647              
2648             my $xml = $self->_sign(Action => 'GetLoginProfile', %args);
2649              
2650             if ( grep { defined && length } $xml->{'Error'} ) {
2651             return $self->_parse_errors($xml);
2652             } else {
2653             return Net::Amazon::IAM::LoginProfile->new(
2654             $xml->{'GetLoginProfileResult'}{'LoginProfile'},
2655             );
2656             }
2657             }
2658              
2659             =head2 update_login_profile(%params)
2660              
2661             Changes the password for the specified user.
2662              
2663             =over
2664              
2665             =item UserName (required)
2666              
2667             The name of the user whose password you want to update.
2668              
2669             =item Password (required)
2670              
2671             The new password for the specified user.
2672              
2673             =item PasswordResetRequired (optional)
2674              
2675             Require the specified user to set a new password on next sign-in.
2676              
2677             =back
2678              
2679             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
2680              
2681             =cut
2682              
2683             sub update_login_profile {
2684             my $self = shift;
2685              
2686             my %args = validate(@_, {
2687             UserName => { type => SCALAR },
2688             Password => { type => SCALAR, optional => 1 },
2689             PasswordResetRequired => { type => SCALAR, optional => 1 },
2690             });
2691              
2692             my $xml = $self->_sign(Action => 'UpdateLoginProfile', %args);
2693              
2694             if ( grep { defined && length } $xml->{'Error'} ) {
2695             return $self->_parse_errors($xml);
2696             } else {
2697             return 1;
2698             }
2699             }
2700              
2701             =head2 update_assume_role_policy(%params)
2702              
2703             Updates the policy that grants an entity permission to assume a role.
2704              
2705             =over
2706              
2707             =item RoleName (required)
2708              
2709             The name of the role to update.
2710              
2711             =item PolicyDocument (required)
2712              
2713             The policy that grants an entity permission to assume the role.
2714              
2715             =back
2716              
2717             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
2718              
2719             =cut
2720              
2721             sub update_assume_role_policy {
2722             my $self = shift;
2723              
2724             my %args = validate(@_, {
2725             RoleName => { type => SCALAR },
2726             PolicyDocument => { type => HASHREF },
2727             });
2728              
2729             $args{'PolicyDocument'} = encode_json delete $args{'PolicyDocument'};
2730            
2731             my $xml = $self->_sign(Action => 'UpdateAssumeRolePolicy', %args);
2732              
2733             if ( grep { defined && length } $xml->{'Error'} ) {
2734             return $self->_parse_errors($xml);
2735             } else {
2736             return 1;
2737             }
2738             }
2739              
2740             =head2 add_client_ID_to_open_ID_connect_provider(%params)
2741              
2742             Adds a new client ID (also known as audience) to the list of client IDs already registered for
2743             the specified IAM OpenID Connect provider.
2744              
2745             This action is idempotent; it does not fail or return an error if you add an existing client
2746             ID to the provider.
2747              
2748             =over
2749              
2750             =item ClientID (required)
2751              
2752             The client ID (also known as audience) to add to the IAM OpenID Connect provider.
2753              
2754             =item OpenIDConnectProviderArn (required)
2755              
2756             The Amazon Resource Name (ARN) of the IAM OpenID Connect (OIDC) provider to add the client ID to.
2757              
2758             =back
2759              
2760             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
2761              
2762             B<This method wasn't tested>
2763              
2764             =cut
2765              
2766             sub add_client_ID_to_open_ID_connect_provider {
2767             my $self = shift;
2768              
2769             my %args = validate(@_, {
2770             ClientID => { type => SCALAR },
2771             OpenIDConnectProviderArn => { type => SCALAR },
2772             });
2773              
2774             my $xml = $self->_sign(Action => 'AddClientIDToOpenIDConnectProvider', %args);
2775              
2776             if ( grep { defined && length } $xml->{'Error'} ) {
2777             return $self->_parse_errors($xml);
2778             } else {
2779             return 1;
2780             }
2781             }
2782              
2783             =head2 create_open_ID_connect_provider(%params)
2784              
2785             Creates an IAM entity to describe an identity provider (IdP) that supports OpenID Connect (OIDC).
2786              
2787             =over
2788              
2789             =item ClientIDList (required)
2790              
2791             A list of client IDs (also known as audiences). When a mobile or web app registers with
2792             an OpenID Connect provider, they establish a value that identifies the application.
2793             (This is the value that's sent as the client_id parameter on OAuth requests.)
2794              
2795             You can register multiple client IDs with the same provider. For example, you might have
2796             multiple applications that use the same OIDC provider. You cannot register more than 100
2797             client IDs with a single IAM OIDC provider.
2798              
2799             =item ThumbprintList (required)
2800              
2801             A list of server certificate thumbprints for the OpenID Connect (OIDC) identity provider's
2802             server certificate(s). Typically this list includes only one entry. However, IAM lets you
2803             have up to five thumbprints for an OIDC provider. This lets you maintain multiple thumbprints
2804             if the identity provider is rotating certificates.
2805              
2806             The server certificate thumbprint is the hex-encoded SHA-1 hash value of the X.509 certificate
2807             used by the domain where the OpenID Connect provider makes its keys available. It is always a
2808             40-character string.
2809              
2810             You must provide at least one thumbprint when creating an IAM OIDC provider. For example, if the
2811             OIDC provider is server.example.com and the provider stores its keys at
2812             "https://keys.server.example.com/openid-connect", the thumbprint string would be the hex-encoded
2813             SHA-1 hash value of the certificate used by https://keys.server.example.com.
2814              
2815             =item Url (required)
2816              
2817             The URL of the identity provider. The URL must begin with "https://" and should correspond to
2818             the iss claim in the provider's OpenID Connect ID tokens. Per the OIDC standard, path components
2819             are allowed but query parameters are not. Typically the URL consists of only a host name, like
2820             "https://server.example.org" or "https://example.com".
2821              
2822             You cannot register the same provider multiple times in a single AWS account. If you try to
2823             submit a URL that has already been used for an OpenID Connect provider in the AWS account,
2824             you will get an error.
2825              
2826             =back
2827              
2828             Returns OpenIDConnectProviderArn on success or L<Net::Amazon::IAM::Error> on fail.
2829              
2830             B<This method wasn't tested>
2831              
2832             =cut
2833              
2834             sub create_open_ID_connect_provider {
2835             my $self = shift;
2836              
2837             my %args = validate(@_, {
2838             ClientIDList => { type => ARRAYREF, optional => 1 },
2839             ThumbprintList => { type => ARRAYREF },
2840             Url => { type => SCALAR },
2841             });
2842              
2843             my $client_ids_list = delete $args{'ClientIDList'};
2844             my $thumb_print_list = delete $args{'ThumbprintList'};
2845              
2846             my $c_count = 1;
2847             for my $id(@{$client_ids_list}) {
2848             $args{'ClientIDList.list.' . $c_count} = $id;
2849             $c_count++;
2850             }
2851              
2852             my $t_count = 1;
2853             for my $thumb(@{$thumb_print_list}) {
2854             $args{'ThumbprintList.list.' . $t_count} = $thumb;
2855             $t_count++;
2856             }
2857              
2858             my $xml = $self->_sign(Action => 'CreateOpenIDConnectProvider', %args);
2859              
2860             if ( grep { defined && length } $xml->{'Error'} ) {
2861             return $self->_parse_errors($xml);
2862             } else {
2863             return $xml->{'CreateOpenIDConnectProviderResult'}{'OpenIDConnectProviderArn'}
2864             }
2865             }
2866              
2867             =head2 delete_open_ID_connect_provider(%params)
2868              
2869             Deletes an IAM OpenID Connect identity provider.
2870              
2871             Deleting an OIDC provider does not update any roles that reference the provider as a
2872             principal in their trust policies. Any attempt to assume a role that references a
2873             provider that has been deleted will fail.
2874              
2875             This action is idempotent; it does not fail or return an error if you call the action
2876             for a provider that was already deleted.
2877              
2878             =over
2879              
2880             =item OpenIDConnectProviderArn (required)
2881              
2882             The Amazon Resource Name (ARN) of the IAM OpenID Connect provider to delete.
2883              
2884             =back
2885              
2886             Returns true on success or L<Net::Amazon::IAM::Error> on fail.
2887              
2888             B<This method wasn't tested>
2889              
2890             =cut
2891              
2892             sub delete_open_ID_connect_provider {
2893             my $self = shift;
2894              
2895             my %args = validate(@_, {
2896             OpenIDConnectProviderArn => { type => SCALAR },
2897             });
2898              
2899             my $xml = $self->_sign(Action => 'DeleteOpenIDConnectProvider', %args);
2900              
2901             if ( grep { defined && length } $xml->{'Error'} ) {
2902             return $self->_parse_errors($xml);
2903             } else {
2904             return 1;
2905             }
2906             }
2907              
2908             =head2 get_group_policy(%params)
2909              
2910             =over
2911              
2912             =item GroupName (required)
2913              
2914             The name of the group the policy is associated with.
2915              
2916             =item PolicyName (required)
2917              
2918             The name of the policy document to get.
2919              
2920             =back
2921              
2922             Returns L<Net::Amazon::IAM::GroupPolicy> on success or L<Net::Amazon::IAM::Error> on fail.
2923              
2924             =cut
2925              
2926             sub get_group_policy {
2927             my $self = shift;
2928              
2929             my %args = validate(@_, {
2930             GroupName => { type => SCALAR },
2931             PolicyName => { type => SCALAR },
2932             });
2933              
2934             my $xml = $self->_sign(Action => 'GetGroupPolicy', %args);
2935              
2936             if ( grep { defined && length } $xml->{'Error'} ) {
2937             return $self->_parse_errors($xml);
2938             } else {
2939             my %result = ${$xml->{'GetGroupPolicyResult'}};
2940             $result{'PolicyDocument'} = decode_json(URI::Encode->new()->decode($result{'PolicyDocument'}));
2941              
2942             return Net::Amazon::IAM::GroupPolicy->new(
2943             %result,
2944             );
2945             }
2946             }
2947              
2948             no Moose;
2949             1;
2950              
2951             =head1 KNOWN ISSUES
2952              
2953             * missing some ( a lot of ) methods
2954              
2955             * missing tests
2956              
2957             * list_user_policies returns just an ArrayRef.
2958              
2959             =head1 SEE ALSO
2960              
2961             =over
2962              
2963             =item Amazon IAM API reference
2964              
2965             http://docs.aws.amazon.com/IAM/latest/APIReference/Welcome.html
2966              
2967             =back
2968              
2969             =head1 AUTHOR
2970              
2971             Igor Tsigankov <tsiganenok@gmail.com>
2972              
2973             =head1 COPYRIGHT
2974              
2975             Copyright (c) 2015 Igor Tsigankov.
2976              
2977             This program is free software; you can redistribute it and/or modify it
2978             under the same terms as Perl itself.
2979              
2980             =cut
2981              
2982             __END__