#!/usr/bin/env perl
use strict;
use warnings;

use Data::Dumper;
use Amazon::API::IAM;
use Amazon::API::STS;
use Amazon::Credentials qw(normalize_arn);
use JSON;
use Text::ASCIITable;

########################################################################
sub get_caller_identity {
########################################################################
  my ($creds) = @_;

  my $sts = Amazon::API::STS->new( credentials => $creds );

  my $result = $sts->GetCallerIdentity();

  return $result;
}

########################################################################
sub main {
########################################################################

  my $creds = Amazon::Credentials->new( no_passkey_warning => 1, imdsv2 => 1, order => [qw(file env role )] );

  my $identity = get_caller_identity($creds);

  my $iam = Amazon::API::IAM->new( credentials => $creds );

  my $permissions_needed = {
    ECR => [
      qw(
        ecr:CreateRepository
        ecr:DescribeRepositories
        ecr:GetAuthorizationToken
        ecr:BatchCheckLayerAvailability
        ecr:PutImage
        ecr:InitiateLayerUpload
        ecr:UploadLayerPart
        ecr:CompleteLayerUpload
        ecr:PutLifecyclePolicy
        ecr:GetLifecyclePolicy)
    ],
    IAM => [
      qw
        (
        iam:GetRole
        iam:CreateRole
        iam:AttachRolePolicy
        iam:PassRole
        iam:ListAttachedRolePolicies
      )
    ],
    LAMBDA => [
      qw
        (
        lambda:GetFunction
        lambda:CreateFunction
        lambda:UpdateFunctionCode
        lambda:GetFunctionConfiguration
        lambda:UpdateFunctionConfiguration
        lambda:InvokeFunction
        lambda:CreateEventSourceMapping
        lambda:ListEventSourceMappings
        lambda:GetPolicy
        lambda:AddPermission
        lambda:RemovePermission
        lambda:CreateFunctionUrlConfig
        lambda:GetFunctionUrlConfig
        lambda:DeleteFunctionUrlConfig
      )
    ],
    SQS => [
      qw(
        sqs:ListQueues
        sqs:CreateQueue)
    ],
    S3 => [
      qw(
        s3:CreateBucket
        s3:ListBuckets
        s3api:PutBucketNotificationConfiguration)
    ],
    EVENTBRIDGE => [
      qw(
        events:DescribeRule
        events:PutRule
        events:PutTargets
        events:RemoveTargets
        events:DeleteRule
        events:EnableRule
        events:DisableRule
      )
    ],
    STS => [
      qw(
        sts:GetCallerIdentity
      )
    ],
    SNS => [
      qw(
        sns:ListTopics
        sns:CreateTopic
        sns:Subscribe
        sns:GetTopicAttributes
      )
    ],
  };

  my @permissions;

  my $t = Text::ASCIITable->new( { headingText => 'Lambda Runtime Builder Permission Check' } );
  $t->setCols(qw(Service Action Status));

  my $cur_service;

  foreach ( sort keys %{$permissions_needed} ) {
    my $result = $iam->SimulatePrincipalPolicy(
      { ActionNames     => $permissions_needed->{$_},
        PolicySourceArn => normalize_arn( $identity->{Arn} ),
      }
    );

    my $evaluation_results = $result->{EvaluationResults};
    foreach my $r ( @{$evaluation_results} ) {

      my ( $service, $action ) = split /[:]/xsm, $r->{EvalActionName};
      my $status = $r->{EvalDecision};

      if ( $cur_service && $cur_service ne $service ) {
        $t->addRowLine;
      }
      $cur_service = $service;

      $t->addRow( $service, $action, $status );
    }

  }

  print {*STDERR} $t;

  return 0;
}

exit main();
