AWSTemplateFormatVersion: 2010-09-09
Description: VPC Analyzer for RDS Custom

Parameters:
  
  VpcId: 
    Description: Enter the VPC id for EC2 instance
    Type: AWS::EC2::VPC::Id

  LatestAmiId:
    Description: Image ID is from Parameter store of SSM. Leave it as-is.
    Type:  "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>"
    Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
    
  EC2SecurityGroup:
    Description: Enter the security group for EC2 observer instance
    Type: AWS::EC2::SecurityGroup::Id
  
  EC2SubnetID:
    Description: Enter the Subnet id for deploying EC2 observer Instance.
    Type: AWS::EC2::Subnet::Id

  Engine:
    Description: Select the engine Oracle or SQL Server
    Type: String
    AllowedValues:
      - Oracle
      - SQLServer

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - 
        Label:
          default: "Existing environmental parameters"
        Parameters:
          - VpcId
      - 
        Label:
          default: ""
        Parameters:
          - LatestAmiId
          - EC2SubnetID
          - EC2SecurityGroup

Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    DependsOn: [profileClientIDE]
    DeletionPolicy: Retain
    Properties:
      InstanceType: 't2.micro'
      ImageId: !Ref LatestAmiId
      IamInstanceProfile: !Ref profileClientIDE
      InstanceInitiatedShutdownBehavior: "terminate"
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeType: gp2
            VolumeSize: '10'
            DeleteOnTermination: 'false'
            Encrypted: 'true'
      Tags:
        - Key: Name
          Value: !Join ['-', ['VPC-Analyzer-EC2', !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]],!Sub "${AWS::Region}"]] 
      NetworkInterfaces: 
        - AssociatePublicIpAddress: "true"
          DeviceIndex: "0"
          GroupSet: 
            - Ref: "EC2SecurityGroup"
          SubnetId: 
            Ref: EC2SubnetID 
      UserData:
        Fn::Base64: !Sub
        - |
          #!/bin/bash
          HOME_DIR=` echo $HOME `
          mkdir -p $HOME_DIR/logs
          LOGFILE=$HOME_DIR/logs/complete-userdata-execution-statements_$$.log
          exec 1> >( tee "${LOGFILE}" ) 2>&1
          curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
          unzip awscliv2.zip
          sudo ./aws/install
          mkdir -p /home/ec2-user/successful_logs
          mkdir -p /home/ec2-user/failed_logs
          echo "$(date +\"%F\ %T\") * running as $(whoami)" >> /home/ec2-user/logs/bootstrap.log
          region=$(sudo aws configure get region)
          Success=()
          fail=()
          niaids=()
          niaidf=()
          if [ -z $region ]
          then
              echo "Error: Couldn't determine the region information using 'sudo aws configure get region'"
              exit
          fi
          echo "$(date +\"%F\ %T\") * running as $(whoami)" >> $HOME_DIR/logs/bootstrap_$$.log
          Engine=$1
          if [ $Engine == "Oracle" ]; then
            vpc_endpoints=("ec2messages.$region.amazonaws.com" "events.$region.amazonaws.com" "logs.$region.amazonaws.com" "monitoring.$region.amazonaws.com" "s3.$region.amazonaws.com" "secretsmanager.$region.amazonaws.com" "ssm.$region.amazonaws.com" "ssmmessages.$region.amazonaws.com")
          elif [ $Engine == "SQLserver" ]; then
            vpc_endpoints=("sqs.$region.amazonaws.com" "ec2.$region.amazonaws.com" "ec2messages.$region.amazonaws.com" "events.$region.amazonaws.com" "logs.$region.amazonaws.com" "monitoring.$region.amazonaws.com" "s3.$region.amazonaws.com" "secretsmanager.$region.amazonaws.com" "ssm.$region.amazonaws.com" "ssmmessages.$region.amazonaws.com")
          else
            echo "Missing or Incorrect argument"
            show_usage
          fi
          INSTANCE_ID=$(ec2-metadata -i | awk -F ":" {'print $2'})
          ip_addresses=()
          for vpc_endpoint in "${vpc_endpoints[@]}"; do
          #  echo "$vpc_endpoint"
            while [ -z "$ip" ]; do
              ip=$(nslookup "$vpc_endpoint" | awk '/^Address: / { print $2 }'| head -1)
              sleep 5
              echo "{\"DestinationAddress\":\"$ip\",\"DestinationPortRange\":{\"FromPort\":443,\"ToPort\":443}}" >  $HOME_DIR/source-filter_$$.json
              ni_path_id=`aws ec2 create-network-insights-path --source $INSTANCE_ID   --filter-at-source file://$HOME_DIR/source-filter_$$.json --protocol TCP --query 'NetworkInsightsPath.NetworkInsightsPathId' --no-cli-pager --output text`
              nia_id=`aws ec2 start-network-insights-analysis --network-insights-path-id $ni_path_id --query 'NetworkInsightsAnalysis.NetworkInsightsAnalysisId' --no-cli-pager --output text`
              echo -e "Analyzing for the Service: $vpc_endpoint"
              echo -e "Network Insights Analysis ID : $nia_id"
              STATUS=""
              while [ "$STATUS" == "" ]; do
                echo -e "Analysis in progress, waiting for 10 sec... "
                sleep 10
                STATUS=`aws ec2 describe-network-insights-analyses --network-insights-analysis-ids $nia_id --query 'NetworkInsightsAnalyses[].NetworkPathFound' --no-cli-pager --output text`
              done
              echo -e "Network Insights Analysis Status : $STATUS"
              if [ "$STATUS" == "True" ]; then
                echo -e "\nFound path to the destination"
                aws ec2 describe-network-insights-analyses --network-insights-analysis-ids $nia_id --query '[ NetworkInsightsAnalyses[*].ForwardPathComponents[*].SequenceNumber, NetworkInsightsAnalyses[*].ForwardPathComponents[*].Component[].Id ]' --no-cli-pager --output table >> $HOME_DIR/successful_logs/Network-Analysis-Successful-ForwardPath-ORACLE-$nia_id-$vpc_endpoint.log
                aws ec2 describe-network-insights-analyses --network-insights-analysis-ids $nia_id --query '[ NetworkInsightsAnalyses[*].ReturnPathComponents[*].SequenceNumber, NetworkInsightsAnalyses[*].ReturnPathComponents[*].Component[].Id ]' --no-cli-pager --output table >> $HOME_DIR/successful_logs/Network-Analysis-Successful-ReturnPath-ORACLE-$nia_id-$vpc_endpoint.log
                Success+=($vpc_endpoint)
                niaids+=($nia_id)
              else
                echo -e "\nNo Path Found to the destination"
                aws ec2 describe-network-insights-analyses --network-insights-analysis-ids $nia_id --query 'NetworkInsightsAnalyses[*].Explanations[*]' --no-cli-pager --output table >> $HOME_DIR/failed_logs/Network-Analysis-Failed-ORACLE-$nia_id-$vpc_endpoint.log
                fail+=($vpc_endpoint)
                niaidf+=($nia_id)
              fi
            done
            ip=""
          done
          echo -e "\nFinal Summary Report:\n**************************************\n"
          for endpoint in "${Success[@]}"
          do
            for niaid in "${niaids[@]}"
            do
              echo "Success: $endpoint --> Click on this link: https://$region.console.aws.amazon.com/networkinsights/home?region=$region#NetworkPathAnalysis:analysisId=$niaid"
            done
          done
          for endpoint in "${fail[@]}"
          do
            for niaid in "${niaidf[@]}"
            do
              echo "Failed: $endpoint --> Click on this link: https://$region.console.aws.amazon.com/networkinsights/home?region=$region#NetworkPathAnalysis:analysisId=$niaidf"
            done
          done
          if [ -f $HOME_DIR/source-filter_$$.json ]; then
            rm -rf $HOME_DIR/source-filter_$$.json
          fi
        - {
          }

  roleClientIDE:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: !Join ['-', ['VPC-Analyzer-Automation-Role', !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]]]]
      Description: "Permits user interaction with AWS APIs from the EC2."
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - "sts:AssumeRole"
            Principal:
              Service:
                - "ec2.amazonaws.com"
      Policies:
        - PolicyName: !Join ['-', ['StackSetExecutionRolePolicy', !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]],!Sub "${AWS::Region}"]]
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - "iam:GetRole"
                  - "iam:GetRolePolicy"
                  - "iam:PassRole"
                  - "iam:DetachRolePolicy"
                  - "iam:DeleteRolePolicy"
                  - "iam:DeleteRole"
                  - "iam:CreateRole"
                  - "iam:AttachRolePolicy"
                  - "iam:PutRolePolicy"
                  - "ce:*"
                  - "tiros:CreateQuery"
                  - "tiros:GetQueryAnswer"
                  - "tiros:GetQueryExplanation"
                Resource:
                  - "arn:aws:iam::*:role/*"
        - 
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - 
                Effect: Allow
                Action: 
                  - ec2:GetTransitGatewayRouteTablePropagations
                  - ec2:DescribeTransitGatewayPeeringAttachments
                  - ec2:SearchTransitGatewayRoutes
                  - ec2:DescribeTransitGatewayRouteTables
                  - ec2:DescribeTransitGatewayVpcAttachments
                  - ec2:DescribeTransitGatewayAttachments
                  - ec2:DescribeTransitGateways
                  - ec2:GetManagedPrefixListEntries
                  - ec2:DescribeManagedPrefixLists
                  - ec2:DescribeAvailabilityZones
                  - ec2:DescribeCustomerGateways
                  - ec2:DescribeInstances
                  - ec2:DescribeInternetGateways
                  - ec2:DescribeNatGateways
                  - ec2:DescribeNetworkAcls
                  - ec2:DescribeNetworkInterfaces
                  - ec2:DescribePrefixLists
                  - ec2:DescribeRegions
                  - ec2:DescribeRouteTables
                  - ec2:DescribeSecurityGroups
                  - ec2:DescribeSubnets
                  - ec2:DescribeVpcEndpoints
                  - ec2:DescribeVpcPeeringConnections
                  - ec2:DescribeVpcs
                  - ec2:DescribeVpnConnections
                  - ec2:DescribeVpnGateways
                  - ec2:DescribeVpcEndpointServiceConfigurations
                  - elasticloadbalancing:DescribeListeners
                  - elasticloadbalancing:DescribeLoadBalancers
                  - elasticloadbalancing:DescribeLoadBalancerAttributes
                  - elasticloadbalancing:DescribeRules
                  - elasticloadbalancing:DescribeTags
                  - elasticloadbalancing:DescribeTargetGroups
                  - elasticloadbalancing:DescribeTargetHealth
                  - tiros:CreateQuery
                  - tiros:GetQueryAnswer
                  - tiros:GetQueryExplanation
                  - ec2:CreateTags
                  - ec2:DeleteTags
                  - ec2:StartNetworkInsightsAnalysis
                  - ec2:DescribeNetworkInsightsAnalyses
                  - ec2:DescribeNetworkInsightsPaths
                Resource: "*"
          PolicyName: !Join ['-', ['StackSetExecutionRolePolicy-Network', !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]],!Sub "${AWS::Region}"]]          
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
        - "arn:aws:iam::aws:policy/AmazonSSMFullAccess"
        - "arn:aws:iam::aws:policy/AmazonSSMDirectoryServiceAccess"
        - "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
        - "arn:aws:iam::aws:policy/AmazonS3FullAccess"
        - "arn:aws:iam::aws:policy/AWSCloudFormationFullAccess"
        - "arn:aws:iam::aws:policy/AWSLambda_FullAccess"
        - "arn:aws:iam::aws:policy/AmazonRDSFullAccess"
        - "arn:aws:iam::aws:policy/SecretsManagerReadWrite"
        - "arn:aws:iam::aws:policy/AmazonEC2FullAccess"
      Tags:
        - Key: Name
          Value: !Join ['-', ['VPC-Analyzer-Automation', !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]]]]        

                      
  profileClientIDE:
    Type: "AWS::IAM::InstanceProfile"
    Properties:
      InstanceProfileName: !Join ['-', ['VPC-Analyzer-Instance-Profile', !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]],!Sub "${AWS::Region}"]]
      Path: /
      Roles:
        - Ref: roleClientIDE  
