Example #1
0
def main(args, pacu_main: 'Main'):
    session = session = pacu_main.get_active_session()

    ###### Don't modify these. They can be removed if you are not using the function.
    args = parser.parse_args(args)
    print = pacu_main.print

    fetch_data = pacu_main.fetch_data
    ######

    task_definitions = []
    summary_data = {"task_definitions": 0}

    if args.task_definitions is not None:
        for task_def in args.task_definitions.split(','):
            task_definitions.append({
                'Task Defintion ID': task_def
            })
    else:
        if fetch_data(['ECS', 'TaskDefinitions'], module_info['prerequisite_modules'][0], '--taskdef') is False:
            print('Pre-req module not run successfully. Exiting...')
            return None
        task_definitions = session.ECS['TaskDefinitions']

    if task_definitions:
        print("Targeting {} task definition(s)...".format(len(task_definitions)))

        for task_def in task_definitions:
            region = task_def.split(':')[3]
            client = pacu_main.get_boto3_client('ecs', region)

            try:
                task_def_data = client.describe_task_definition(
                    taskDefinition=task_def,
                )
            except ClientError as error:
                code = error.response['Error']['Code']
                print('FAILURE: ')
                if code == 'AccessDenied':
                    print('  Access denied to DescribeTaskDefinition.')
                    print('Skipping the rest of the task definitions...')
                    break
                else:
                    print('  ' + code)

            formatted_data = "{}@{}\n{}\n\n".format(
                task_def,
                region,
                json.dumps(task_def_data['taskDefinition'], indent=4, default=str)
            )

            with save('ecs_task_def_data/all_task_def.txt'.format(session.name), 'a+') as f:
                f.write(formatted_data)
            with save('ecs_task_def_data/{}.txt'.format(session.name, task_def.split('/')[1].split(':')[0])) as f:
                f.write(formatted_data.replace('\\t', '\t').replace('\\n', '\n').rstrip())
            summary_data['task_definitions'] += 1

    return summary_data
Example #2
0
def write_bucket_keys_to_file(pacu, objects):
    pacu.print('  Writing file names to disk...')
    session = pacu.get_active_session()
    p = '{}/{}_file_names.txt'.format(module_info['name'], module_info['name'])
    try:
        with save(p, 'w') as objects_file:
            for key in objects:
                for file in objects[key]:
                    objects_file.write('{}@{}\n'.format(file, key))
    except Exception as error:
        print(error)
    return True
Example #3
0
def write_stream_file(session_name, scan_time, group_name, stream_name,
                      events):
    if not events:
        return True
    stream_group_path = os.path.join('cloud_watch_logs', str(scan_time),
                                     group_name[1:])
    file_name = os.path.join(stream_group_path,
                             stream_name.replace('/', '_') + '.csv')

    with save(file_name, 'a', newline='') as f:
        event_writer = csv.writer(f, delimiter=',')
        for event in events:
            event_writer.writerow([event['timestamp'], event['message']])
    return True
Example #4
0
def main(args, pacu_main: 'Main'):
    session = pacu_main.get_active_session()

    ###### Don't modify these. They can be removed if you are not using the function.
    args = parser.parse_args(args)
    print = pacu_main.print

    get_regions = pacu_main.get_regions
    ######
    summary_data = {}
    if args.regions is None:
        regions = get_regions('cloudtrail')
        if regions is None or regions == [] or regions == '' or regions == {}:
            print(
                'This module is not supported in any regions specified in the current sessions region set. Exiting...'
            )
            return
    else:
        regions = args.regions.split(',')

    for region in regions:
        events = []
        print('Downloading logs from {}:'.format(region))
        print(' This may take a while...')
        client = pacu_main.get_boto3_client('cloudtrail', region)

        event_history = client.lookup_events(MaxResults=50, )
        events += event_history['Events']

        while 'NextToken' in event_history:
            print('  Processing additional results...')
            event_history = client.lookup_events(
                MaxResults=50, NextToken=event_history['NextToken'])
            events += event_history['Events']

        summary_data[region] = len(events)
        print('Finished enumerating {}'.format(region))

        now = time.time()
        filename = 'cloudtrail_{}_event_history_{}.json'.format(region, now)
        with save(filename) as f:
            json.dump(events, f, indent=2, default=str)
        print('  Events written to {}/cloudtrail_{}_event_history_{}.json'.
              format(downloads_dir(), region, now))

    return summary_data
Example #5
0
def download_s3_file(pacu, key, bucket):
    s3 = pacu.get_boto3_resource('s3')
    base_directory = '{}/{}/'.format(module_info['name'], bucket)

    size = s3.Object(bucket, key).content_length
    if size > FILE_SIZE_THRESHOLD:
        pacu.print('  LARGE FILE DETECTED:')
        confirm = pacu.input('    Download {}? Size: {} bytes (y/n) '.format(key, size))
        if confirm != 'y':
            return False
    try:
        with save(base_directory + key) as f:
            s3.Bucket(bucket).download_fileobj(key, f)
    except Exception as error:
        pacu.print('  {}'.format(error))
        return False
    return True
Example #6
0
def main(args, pacu_main: 'Main'):
    session = pacu_main.get_active_session()

    args = parser.parse_args(args)
    print = pacu_main.print

    get_regions = pacu_main.get_regions
    if not args.regions:
        regions = get_regions('elasticloadbalancing')
    else:
        regions = args.regions.split(',')
    summary_data = {'load_balancers': 0}
    if 'LoadBalancers' not in session.EC2.keys():
        ec2_data = deepcopy(session.EC2)
        ec2_data['LoadBalancers'] = []
        session.update(pacu_main.database, EC2=ec2_data)

    load_balancers = list()
    for region in regions:
        print('Starting region {}...'.format(region))
        client = pacu_main.get_boto3_client('elbv2', region)

        count = 0
        response = None
        next_marker = False

        while (response is None or 'NextMarker' in response):
            try:
                if next_marker is False:
                    response = client.describe_load_balancers()
                else:
                    response = client.describe_load_balancers(
                        Marker=next_marker)

                if 'NextMarker' in response:
                    next_marker = response['NextMarker']
                for load_balancer in response['LoadBalancers']:
                    load_balancer['Region'] = region
                    # Adding Attributes to current load balancer database
                    load_balancer[
                        'Attributes'] = client.describe_load_balancer_attributes(
                            LoadBalancerArn=load_balancer['LoadBalancerArn']
                        )['Attributes']
                    load_balancers.append(load_balancer)
            except ClientError as error:
                if error.response['Error']['Code'] == 'AccessDenied':
                    print('  FAILURE: MISSING REQUIRED AWS PERMISSIONS')
                else:
                    print('  {}'.format(error.response['Error']['Code']))
                break
            if response and 'LoadBalancers' in response:
                count += len(response['LoadBalancers'])
        summary_data['load_balancers'] += count
        print('  {} load balancer(s) found '.format(count))

    ec2_data = deepcopy(session.EC2)
    ec2_data['LoadBalancers'] = deepcopy(load_balancers)
    session.update(pacu_main.database, EC2=ec2_data)

    print('\n{} total load balancer(s) found.'.format(
        len(session.EC2['LoadBalancers'])))

    now = time.time()
    p = 'elbs_no_logs_{}.csv'.format(now)
    summary_data['csv_file_path'] = p
    summary_data['logless'] = 0

    with save(p, 'w+') as f:
        f.write('Load Balancer Name,Load Balancer ARN,Region\n')
        for load_balancer in session.EC2['LoadBalancers']:
            for attribute in load_balancer['Attributes']:
                if attribute['Key'] == 'access_logs.s3.enabled':
                    if attribute['Value'] is False or attribute[
                            'Value'] == 'false':
                        f.write('{},{},{}\n'.format(
                            load_balancer['LoadBalancerName'],
                            load_balancer['LoadBalancerArn'],
                            load_balancer['Region']))
                        summary_data['logless'] += 1
    return summary_data
Example #7
0
def main(args, pacu_main):
    session = pacu_main.get_active_session()

    args = parser.parse_args(args)
    print = pacu_main.print
    get_regions = pacu_main.get_regions

    if args.instances is False and args.security_groups is False and args.elastic_ips is False and args.public_ips is False and args.customer_gateways is False and args.dedicated_hosts is False and args.network_acls is False and args.nat_gateways is False and args.network_interfaces is False and args.route_tables is False and args.subnets is False and args.vpcs is False and args.vpc_endpoints is False and args.launch_templates is False:
        args.instances = args.security_groups = args.elastic_ips = args.public_ips = args.customer_gateways = args.dedicated_hosts = args.network_acls = args.nat_gateways = args.network_interfaces = args.route_tables = args.subnets = args.vpcs = args.vpc_endpoints = args.launch_templates = True

    if args.regions is None:
        regions = get_regions('ec2')
        if regions is None or regions == [] or regions == '' or regions == {}:
            print(
                'This module is not supported in any regions specified in the current sessions region set. Exiting...'
            )
            return
    else:
        regions = args.regions.split(',')

    client = pacu_main.get_boto3_client('ec2', choice(regions))

    all_instances = []
    all_security_groups = []
    all_elastic_ips = []
    all_public_ips = []
    all_vpn_customer_gateways = []
    all_dedicated_hosts = []
    all_network_acls = []
    all_nat_gateways = []
    all_network_interfaces = []
    all_route_tables = []
    all_subnets = []
    all_vpcs = []
    all_vpc_endpoints = []
    all_launch_templates = []
    for region in regions:
        instances = []
        security_groups = []
        elastic_ips = []
        public_ips = []
        vpn_customer_gateways = []
        dedicated_hosts = []
        network_acls = []
        nat_gateways = []
        network_interfaces = []
        route_tables = []
        subnets = []
        vpcs = []
        vpc_endpoints = []
        launch_templates = []

        if any([
                args.instances, args.security_groups, args.elastic_ips,
                args.public_ips, args.customer_gateways, args.dedicated_hosts,
                args.network_acls, args.nat_gateways, args.network_interfaces,
                args.route_tables, args.subnets, args.vpcs, args.vpc_endpoints,
                args.launch_templates
        ]):
            print('Starting region {}...'.format(region))
        client = pacu_main.get_boto3_client('ec2', region)

        # Instances
        if args.instances:
            response = None
            next_token = False
            while (response is None or 'NextToken' in response):
                if next_token is False:
                    try:
                        response = client.describe_instances(
                            MaxResults=
                            1000  # To prevent timeouts if there are too many instances
                        )
                    except ClientError as error:
                        code = error.response['Error']['Code']
                        print('FAILURE: ')
                        if code == 'UnauthorizedOperation':
                            print('  Access denied to DescribeInstances.')
                        else:
                            print('  ' + code)
                        print('  Skipping instance enumeration...')
                        args.instances = False
                        break
                else:
                    response = client.describe_instances(MaxResults=1000,
                                                         NextToken=next_token)
                if 'NextToken' in response:
                    next_token = response['NextToken']
                for reservation in response['Reservations']:
                    for instance in reservation['Instances']:
                        instance['Region'] = region
                        instances.append(instance)
                        # Scan tags for secrets
                        scan_tags(instance)

            print('  {} instance(s) found.'.format(len(instances)))
            all_instances += instances

        # Security Groups
        if args.security_groups:
            response = None
            next_token = False
            while (response is None or 'NextToken' in response):
                if next_token is False:
                    try:
                        response = client.describe_security_groups(
                            MaxResults=1000)
                    except ClientError as error:
                        code = error.response['Error']['Code']
                        print('FAILURE: ')
                        if code == 'UnauthorizedOperation':
                            print('  Access denied to DescribeSecurityGroups.')
                        else:
                            print('  ' + code)
                        print('    Skipping security group enumeration...')
                        args.security_groups = False
                        break
                else:
                    response = client.describe_security_groups(
                        NextToken=next_token, MaxResults=1000)
                if 'NextToken' in response:
                    next_token = response['NextToken']
                for group in response['SecurityGroups']:
                    group['Region'] = region
                    security_groups.append(group)
            print('  {} security groups(s) found.'.format(
                len(security_groups)))
            all_security_groups += security_groups

        # Elastic IPs
        if args.elastic_ips:
            try:
                response = client.describe_addresses()
                for ip in response['Addresses']:
                    ip['Region'] = region
                    elastic_ips.append(ip)
            except ClientError as error:
                code = error.response['Error']['Code']
                print('FAILURE: ')
                if code == 'UnauthorizedOperation':
                    print('  Access denied to DescribeAddresses.')
                else:
                    print('  ' + code)
                print('    Skipping elastic IP enumeration...')
                args.elastic_ips = False
            print('  {} elastic IP address(es) found.'.format(
                len(elastic_ips)))
            all_elastic_ips += elastic_ips

        # Public IPs
        if args.public_ips:
            p = 'ec2_public_ips_{}_{}.txt'.format(session.name, region)
            response = None
            next_token = False
            while (response is None or 'NextToken' in response):
                if next_token is False:
                    try:
                        response = client.describe_instances(MaxResults=1000)
                        for reservation in response['Reservations']:
                            for instance in reservation['Instances']:
                                public = instance.get("PublicIpAddress")
                                if public:
                                    public_ips.append(public)
                    except ClientError as error:
                        code = error.response['Error']['Code']
                        print('FAILURE: ')
                        if code == 'UnauthorizedOperation':
                            print('  Access denied to DescribeInstances.')
                        else:
                            print('  ' + code)
                        print('  Skipping public IP enumeration...')
                        args.instances = False
                        break
                else:
                    response = client.describe_instances(MaxResults=1000,
                                                         NextToken=next_token)
                    for reservation in response['Reservations']:
                        for instance in reservation['Instances']:
                            public = instance["PublicIpAddress"]
                            if public:
                                public_ips.append(public)
                if 'NextToken' in response:
                    next_token = response['NextToken']
            if len(public_ips) > 0:
                with save(p, 'w+') as f:
                    for public in public_ips:
                        f.write('{}\n'.format(public))
            print(
                '  {} publics IP address(es) found and added to text file located at: ~/.local/share/pacu/{}/downloads/{}'
                .format(len(public_ips), session.name, p))
            all_public_ips += public_ips

        # VPN Customer Gateways
        if args.customer_gateways:
            try:
                response = client.describe_customer_gateways()
                for gateway in response['CustomerGateways']:
                    gateway['Region'] = region
                    vpn_customer_gateways.append(gateway)
            except ClientError as error:
                code = error.response['Error']['Code']
                print('FAILURE: ')
                if code == 'UnauthorizedOperation':
                    print('  Access denied to DescribeCustomerGateways.')
                else:
                    print('  ' + code)
                print('    Skipping VPN customer gateway enumeration...')
                args.customer_gateways = False
            print('  {} VPN customer gateway(s) found.'.format(
                len(vpn_customer_gateways)))
            all_vpn_customer_gateways += vpn_customer_gateways

        # Dedicated Hosts
        if args.dedicated_hosts:
            response = None
            next_token = False
            while (response is None or 'NextToken' in response):
                if next_token is False:
                    try:
                        response = client.describe_hosts(MaxResults=500)
                    except ClientError as error:
                        code = error.response['Error']['Code']
                        print('FAILURE: ')
                        if code == 'UnauthorizedOperation':
                            print('  Access denied to DescribeHosts.')
                        else:
                            print('  ' + code)
                        print('    Skipping dedicated host enumeration...')
                        args.dedicated_hosts = False
                        break
                else:
                    response = client.describe_hosts(NextToken=next_token,
                                                     MaxResults=500)
                if 'NextToken' in response:
                    next_token = response['NextToken']
                for host in response['Hosts']:
                    host['Region'] = region
                    dedicated_hosts.append(host)
            print('  {} dedicated host(s) found.'.format(len(dedicated_hosts)))
            all_dedicated_hosts += dedicated_hosts

        # Network ACLs
        if args.network_acls:
            try:
                response = client.describe_network_acls()
                for acl in response['NetworkAcls']:
                    acl['Region'] = region
                    network_acls.append(acl)
            except ClientError as error:
                code = error.response['Error']['Code']
                print('FAILURE: ')
                if code == 'UnauthorizedOperation':
                    print('  Access denied to DescribeNetworkACLs.')
                else:
                    print('  ' + code)
                print('    Skipping network ACL enumeration...')
                args.network_acls = False
            print('  {} network ACL(s) found.'.format(len(network_acls)))
            all_network_acls += network_acls

        # NAT Gateways
        if args.nat_gateways:
            response = None
            next_token = False
            while (response is None or 'NextToken' in response):
                if next_token is False:
                    try:
                        response = client.describe_nat_gateways(
                            MaxResults=1000)
                    except ClientError as error:
                        code = error.response['Error']['Code']
                        print('FAILURE: ')
                        if code == 'UnauthorizedOperation':
                            print('  Access denied to DescribeNATGateways.')
                        else:
                            print('  ' + code)
                        print('    Skipping NAT gateway enumeration...')
                        args.nat_gateways = False
                        break
                else:
                    response = client.describe_nat_gateways(
                        NextToken=next_token, MaxResults=1000)
                if 'NextToken' in response:
                    next_token = response['NextToken']
                for gateway in response['NatGateways']:
                    gateway['Region'] = region
                    nat_gateways.append(gateway)
            print('  {} NAT gateway(s) found.'.format(len(nat_gateways)))
            all_nat_gateways += nat_gateways

        # Network Interfaces
        if args.network_interfaces:
            try:
                response = client.describe_network_interfaces()
                for interface in response['NetworkInterfaces']:
                    interface['Region'] = region
                    network_interfaces.append(interface)
            except ClientError as error:
                code = error.response['Error']['Code']
                print('FAILURE: ')
                if code == 'UnauthorizedOperation':
                    print('  Access denied to DescribeNetworkInterfaces.')
                else:
                    print('  ' + code)
                print('    Skipping network interface enumeration...')
                args.network_interfaces = False
            print('  {} network interface(s) found.'.format(
                len(network_interfaces)))
            all_network_interfaces += network_interfaces

        # Route Tables
        if args.route_tables:
            try:
                response = client.describe_route_tables()
                for table in response['RouteTables']:
                    table['Region'] = region
                    route_tables.append(table)
            except ClientError as error:
                code = error.response['Error']['Code']
                print('FAILURE: ')
                if code == 'UnauthorizedOperation':
                    print('  Access denied to DescribeRouteTables.')
                else:
                    print('  ' + code)
                print('    Skipping route table enumeration...')
                args.route_tables = False
            print('  {} route table(s) found.'.format(len(route_tables)))
            all_route_tables += route_tables

        # Subnets
        if args.subnets:
            try:
                response = client.describe_subnets()
                for subnet in response['Subnets']:
                    subnet['Region'] = region
                    subnets.append(subnet)
            except ClientError as error:
                code = error.response['Error']['Code']
                print('FAILURE: ')
                if code == 'UnauthorizedOperation':
                    print('  Access denied to DescribeSubnets.')
                else:
                    print('  ' + code)
                print('    Skipping subnet enumeration...')
                args.subnets = False
            print('  {} subnet(s) found.'.format(len(subnets)))
            all_subnets += subnets

        # VPCs
        if args.vpcs:
            try:
                response = client.describe_vpcs()
                for vpc in response['Vpcs']:
                    vpc['Region'] = region
                    vpcs.append(vpc)
            except ClientError as error:
                code = error.response['Error']['Code']
                print('FAILURE: ')
                if code == 'UnauthorizedOperation':
                    print('  Access denied to DescribeVPCs.')
                else:
                    print('  ' + code)
                print('    Skipping VPC enumeration...')
                args.vpcs = False
            print('  {} VPC(s) found.'.format(len(vpcs)))
            all_vpcs += vpcs

        # VPC Endpoints
        if args.vpc_endpoints:
            response = None
            next_token = False
            while (response is None or 'NextToken' in response):
                if next_token is False:
                    try:
                        response = client.describe_vpc_endpoints(
                            MaxResults=1000)
                    except ClientError as error:
                        code = error.response['Error']['Code']
                        print('FAILURE: ')
                        if code == 'UnauthorizedOperation':
                            print('  Access denied to DescribeVPCEndpoints.')
                        else:
                            print('  ' + code)
                        print('    Skipping VPC endpoint enumeration...')
                        args.vpc_endpoints = False
                        break
                else:
                    response = client.describe_vpc_endpoints(
                        NextToken=next_token, MaxResults=1000)
                if 'NextToken' in response:
                    next_token = response['NextToken']
                for endpoint in response['VpcEndpoints']:
                    endpoint['Region'] = region
                    vpc_endpoints.append(endpoint)
            print('  {} VPC endpoint(s) found.'.format(len(vpc_endpoints)))
            all_vpc_endpoints += vpc_endpoints

        # Launch Templates
        if args.launch_templates:
            response = None
            next_token = False
            while (response is None or 'NextToken' in response):
                if next_token is False:
                    try:
                        response = client.describe_launch_templates()
                    except ClientError as error:
                        code = error.response['Error']['Code']
                        print('FAILURE: ')
                        if code == 'UnauthorizedOperation':
                            print(
                                '  Access denied to DescribeLaunchTemplates.')
                        else:
                            print('  ' + code)
                        print('    Skipping launch template enumeration...')
                        args.launch_templates = False
                        break
                else:
                    response = client.describe_launch_templates(
                        NextToken=next_token)
                if 'NextToken' in response:
                    next_token = response['NextToken']
                for template in response['LaunchTemplates']:
                    template['Region'] = region
                    launch_templates.append(template)
            print('  {} launch template(s) found.'.format(
                len(launch_templates)))
            all_launch_templates += launch_templates

    gathered_data = {
        'Instances': all_instances,
        'SecurityGroups': all_security_groups,
        'ElasticIPs': all_elastic_ips,
        'PublicIPs': all_public_ips,
        'VPNCustomerGateways': all_vpn_customer_gateways,
        'DedicatedHosts': all_dedicated_hosts,
        'NetworkACLs': all_network_acls,
        'NATGateways': all_nat_gateways,
        'NetworkInterfaces': all_network_interfaces,
        'RouteTables': all_route_tables,
        'Subnets': all_subnets,
        'VPCs': all_vpcs,
        'VPCEndpoints': all_vpc_endpoints,
        'LaunchTemplates': all_launch_templates,
    }

    for var in vars(args):
        if var == 'regions':
            continue
        if not getattr(args, var):
            del gathered_data[ARG_FIELD_MAPPER[var]]

    ec2_data = deepcopy(session.EC2)
    for key, value in gathered_data.items():
        ec2_data[key] = value
    session.update(pacu_main.database, EC2=ec2_data)

    # Add regions to gathered_data for summary output
    gathered_data['regions'] = regions

    if any([
            args.instances, args.security_groups, args.elastic_ips,
            args.customer_gateways, args.dedicated_hosts, args.network_acls,
            args.nat_gateways, args.network_interfaces, args.route_tables,
            args.subnets, args.vpcs, args.vpc_endpoints, args.launch_templates
    ]):
        return gathered_data
    else:
        print('No data successfully enumerated.\n')
        return None
Example #8
0
def main(args, pacu_main: 'Main'):
    session = pacu_main.get_active_session()
    args = parser.parse_args(args)
    print = pacu_main.print

    get_regions = pacu_main.get_regions

    regions = get_regions('Inspector')
    complete_data = {}
    summary_data = {
        'reports': 0,
        'findings': 0,
        'regions': regions,
    }
    if args.download_reports:
        summary_data['reports_location'] = downloads_dir(
        ) / 'inspector_assessments/'
    for region in regions:
        print('Starting region {}...'.format(region))

        client = pacu_main.get_boto3_client('inspector', region)

        if args.download_reports:
            assessment_runs = []
            response = ''
            try:
                response = client.list_assessment_runs()
                assessment_runs += response['assessmentRunArns']
                while 'nextToken' in response:
                    response = client.list_findings(
                        nextToken=response['nextToken'])
                    assessment_runs += response['assessmentRunArns']
            except ClientError as error:
                if error.response['Error']['Code'] == 'AccessDeniedException':
                    print('Access Denied for list-assessment-runs')
            if not assessment_runs:
                print('  No assessment runs found for {}'.format(region))
            else:
                summary_data['reports'] += len(assessment_runs)
            for run in assessment_runs:
                response = client.get_assessment_report(
                    assessmentRunArn=run,
                    reportFileFormat='HTML',
                    reportType='FULL')
                if response.get('url'):
                    p = 'inspector_assessments/'.format(
                        session.name) + str(run)[-10:] + '.html'
                    print('  Report saved to: ' + p)
                    with urllib.request.urlopen(
                            response['url']) as response, save(p, 'a') as f:
                        f.write(str(response.read()))
                else:
                    print('Failed to generate report for {} ({})...'.format(
                        run, response['status']))
        findings = []
        try:
            response = client.list_findings()
            findings = response['findingArns']
            while 'nextToken' in response:
                response = client.list_findings(
                    nextToken=response['nextToken'])
                findings += response['findingArns']
        except ClientError as error:
            if error.response['Error']['Code'] == 'AccessDeniedException':
                print('Access Denied for list-findings')
                continue
        try:
            if len(findings) < 1:
                print('  No findings found')
                continue
            else:
                print('  {} findings found'.format(len(findings)))
                summary_data['findings'] += len(findings)
            descriptions = client.describe_findings(
                findingArns=findings)['findings']
            complete_data[region] = descriptions
        except ClientError as error:
            if error.response['Error']['Code'] == 'AccessDeniedException':
                print('Access Denied for describe-findings')
    session.update(pacu_main.database, Inspector=complete_data)
    return summary_data
Example #9
0
def main(args, pacu_main: 'Main'):
    session = pacu_main.get_active_session()

    ###### Don't modify these. They can be removed if you are not using the function.
    args = parser.parse_args(args)
    print = pacu_main.print
    input = pacu_main.input

    key_info = pacu_main.key_info
    fetch_data = pacu_main.fetch_data
    ######

    summary_data = {'users_confirmed': 0, 'roles_confirmed': 0}

    users = []
    roles = []

    if args.all_users is True:
        if fetch_data(['IAM', 'Users'], module_info['prerequisite_modules'][0],
                      '--users') is False:
            print('FAILURE')
            print('  SUB-MODULE EXECUTION FAILED')
            return
        fetched_users = session.IAM['Users']
        for user in fetched_users:
            users.append({
                'UserName': user['UserName'],
                'PermissionsConfirmed': True,
                'Permissions': {
                    'Allow': {},
                    'Deny': {}
                }
            })
    elif args.user_name is not None:
        users.append({
            'UserName': args.user_name,
            'PermissionsConfirmed': True,
            'Permissions': {
                'Allow': {},
                'Deny': {}
            }
        })
        summary_data['single_user'] = args.user_name

    if args.all_roles is True:
        if fetch_data(['IAM', 'Roles'], module_info['prerequisite_modules'][0],
                      '--roles') is False:
            print('FAILURE')
            print('  SUB-MODULE EXECUTION FAILED')
            return
        fetched_roles = session.IAM['Roles']
        for role in fetched_roles:
            roles.append({
                'RoleName': role['RoleName'],
                'PermissionsConfirmed': True,
                'Permissions': {
                    'Allow': {},
                    'Deny': {}
                }
            })
    elif args.role_name is not None:
        roles.append({
            'RoleName': args.role_name,
            'PermissionsConfirmed': True,
            'Permissions': {
                'Allow': {},
                'Deny': {}
            }
        })
        summary_data['single_role'] = args.role_name

    is_user = is_role = False

    if not any(
        [args.all_users, args.user_name, args.all_roles, args.role_name]):
        client = pacu_main.get_boto3_client('sts')
        identity = client.get_caller_identity()
        active_aws_key = session.get_active_aws_key(pacu_main.database)

        if re.match(r'arn:aws:iam::\d{12}:user/', identity['Arn']) is not None:
            is_user = True
            client = pacu_main.get_boto3_client('iam')
            try:
                user = client.get_user()
                active_aws_key.update(pacu_main.database,
                                      user_name=user['User']['UserName'],
                                      arn=identity['Arn'],
                                      user_id=identity['UserId'],
                                      account_id=identity['Account'])
            except botocore.exceptions.ClientError:
                username = input(
                    'Failed to discover the current users username, enter it now or Ctrl+C to exit the module: '
                ).strip()
                if username:
                    active_aws_key.update(pacu_main.database,
                                          user_name=username,
                                          arn=identity['Arn'],
                                          user_id=identity['UserId'],
                                          account_id=identity['Account'])
                else:
                    # Update the information from get_caller_identity and exit
                    active_aws_key.update(pacu_main.database,
                                          arn=identity['Arn'],
                                          user_id=identity['UserId'],
                                          account_id=identity['Account'])
                    return False
        elif re.match(r'arn:aws:sts::\d{12}:assumed-role/',
                      identity['Arn']) is not None:
            is_role = True
            active_aws_key.update(pacu_main.database,
                                  role_name=identity['Arn'].split(
                                      ':assumed-role/')[1].split('/')[-2],
                                  arn=identity['Arn'],
                                  user_id=identity['UserId'],
                                  account_id=identity['Account'])
        else:
            print('Not an IAM user or role. Exiting...\n')
            return False

        if is_user:
            user = key_info(alias=session.key_alias)
            user['PermissionsConfirmed'] = True
            user['Permissions'] = {'Allow': {}, 'Deny': {}}
            users.append(user)
            summary_data['single_user'] = user['UserName']
        elif is_role:
            roles.append({
                'RoleName': active_aws_key.role_name,
                'PermissionsConfirmed': True,
                'Permissions': {
                    'Allow': {},
                    'Deny': {}
                }
            })
            summary_data['single_role'] = active_aws_key.role_name

    # list-groups-for-user
    # list-user-policies
    # list-group-policies
    # list-role-policies
    # list-attached-role-policies
    # list-attached-group-policies
    # list-attached-user-policies
    # get-policy
    # get-policy-version
    # get-user-policy
    # get-group-policy
    # get-role-policy

    client = pacu_main.get_boto3_client('iam')
    if any([args.all_users, args.user_name, args.all_roles, args.role_name]):
        print('Permission Document Location:')
        print('  {}/confirmed_permissions/\n'.format(downloads_dir()))

    if roles:
        print('Confirming permissions for roles:')
        for role in roles:
            print('  {}...'.format(role['RoleName']))
            role['Policies'] = []

            try:
                # Get inline role policies
                policies = []
                try:
                    response = client.list_role_policies(
                        RoleName=role['RoleName'])
                    policies = response['PolicyNames']
                    while 'IsTruncated' in response and response[
                            'IsTruncated'] is True:
                        response = client.list_role_policies(
                            RoleName=role['RoleName'],
                            Marker=response['Marker'])
                        policies += response['PolicyNames']
                    for policy in policies:
                        role['Policies'].append({'PolicyName': policy})
                except ClientError as error:
                    print('    List role policies failed')
                    if error.response['Error']['Code'] == 'AccessDenied':
                        print(
                            '      FAILURE: MISSING REQUIRED AWS PERMISSIONS')
                    else:
                        print('      {}'.format(
                            error.response['Error']['Code']))
                    role['PermissionsConfirmed'] = False

                # Get document for each inline policy
                for policy in policies:
                    try:
                        document = client.get_role_policy(
                            RoleName=role['RoleName'],
                            PolicyName=policy)['PolicyDocument']
                    except ClientError as error:
                        print('    Get role policy failed')
                        if error.response['Error']['Code'] == 'AccessDenied':
                            print(
                                '      FAILURE: MISSING REQUIRED AWS PERMISSIONS'
                            )
                        else:
                            print('      {}'.format(
                                error.response['Error']['Code']))
                        role['PermissionsConfirmed'] = False
                    role = parse_document(document, role)

                # Get attached role policies
                attached_policies = []
                try:
                    response = client.list_attached_role_policies(
                        RoleName=role['RoleName'])
                    attached_policies = response['AttachedPolicies']
                    while 'IsTruncated' in response and response[
                            'IsTruncated'] is True:
                        response = client.list_attached_role_policies(
                            RoleName=role['RoleName'],
                            Marker=response['Marker'])
                        attached_policies += response['AttachedPolicies']
                    role['Policies'] += attached_policies
                except ClientError as error:
                    print('    List attached role policies failed')
                    if error.response['Error']['Code'] == 'AccessDenied':
                        print(
                            '      FAILURE: MISSING REQUIRED AWS PERMISSIONS')
                    else:
                        print('      {}'.format(
                            error.response['Error']['Code']))
                    role['PermissionsConfirmed'] = False

                role = parse_attached_policies(client, attached_policies, role)
                if role['PermissionsConfirmed']:
                    summary_data['roles_confirmed'] += 1

                if args.role_name is None and args.all_roles is False:
                    print('    Confirmed permissions for {}'.format(
                        role['RoleName']))
                    active_aws_key.update(
                        pacu_main.database,
                        role_name=role['RoleName'],
                        policies=role['Policies'],
                        permissions_confirmed=role['PermissionsConfirmed'],
                        allow_permissions=role['Permissions']['Allow'],
                        deny_permissions=role['Permissions']['Deny'])
                else:
                    with save(
                            'confirmed_permissions/role-{}.json'.format(
                                role['RoleName']), 'w+') as f:
                        json.dump(role, f, indent=2, default=str)

                    print('    Permissions stored in role-{}.json'.format(
                        role['RoleName']))
            except ClientError as error:
                if error.response['Error']['Code'] == 'AccessDenied':
                    print('  FAILURE: MISSING REQUIRED AWS PERMISSIONS')
                else:
                    print('  {}'.format(error.response['Error']['Code']))
                print('Skipping {}'.format(role['RoleName']))
        if users:
            print()

    if users:
        print('Confirming permissions for users:')
        for user in users:
            print('  {}...'.format(user['UserName']))
            user['Groups'] = []
            user['Policies'] = []
            try:
                policies = []

                # Get groups that the user is in
                try:
                    response = client.list_groups_for_user(
                        UserName=user['UserName'])
                    user['Groups'] = response['Groups']
                    while 'IsTruncated' in response and response[
                            'IsTruncated'] is True:
                        response = client.list_groups_for_user(
                            UserName=user['UserName'],
                            Marker=response['Marker'])
                        user['Groups'] += response['Groups']
                except ClientError as error:
                    print('    List groups for user failed')
                    if error.response['Error']['Code'] == 'AccessDenied':
                        print(
                            '      FAILURE: MISSING REQUIRED AWS PERMISSIONS')
                    else:
                        print('      {}'.format(
                            error.response['Error']['Code']))
                    user['PermissionsConfirmed'] = False

                # Get inline and attached group policies
                for group in user['Groups']:
                    group['Policies'] = []
                    # Get inline group policies
                    try:
                        response = client.list_group_policies(
                            GroupName=group['GroupName'])
                        policies = response['PolicyNames']
                        while 'IsTruncated' in response and response[
                                'IsTruncated'] is True:
                            response = client.list_group_policies(
                                GroupName=group['GroupName'],
                                Marker=response['Marker'])
                            policies += response['PolicyNames']
                    except ClientError as error:
                        print('     List group policies failed')
                        if error.response['Error']['Code'] == 'AccessDenied':
                            print(
                                '      FAILURE: MISSING REQUIRED AWS PERMISSIONS'
                            )
                        else:
                            print('      {}'.format(
                                error.response['Error']['Code']))
                        user['PermissionsConfirmed'] = False

                    # Get document for each inline policy
                    for policy in policies:
                        group['Policies'].append(
                            {  # Add policies to list of policies for this group
                                'PolicyName': policy
                            })
                        try:
                            document = client.get_group_policy(
                                GroupName=group['GroupName'],
                                PolicyName=policy)['PolicyDocument']
                        except ClientError as error:
                            print('     Get group policy failed')
                            if error.response['Error'][
                                    'Code'] == 'AccessDenied':
                                print(
                                    '      FAILURE: MISSING REQUIRED AWS PERMISSIONS'
                                )
                            else:
                                print('      {}'.format(
                                    error.response['Error']['Code']))
                            user['PermissionsConfirmed'] = False
                        user = parse_document(document, user)

                    # Get attached group policies
                    attached_policies = []
                    try:
                        response = client.list_attached_group_policies(
                            GroupName=group['GroupName'])
                        attached_policies = response['AttachedPolicies']
                        while 'IsTruncated' in response and response[
                                'IsTruncated'] is True:
                            response = client.list_attached_group_policies(
                                GroupName=group['GroupName'],
                                Marker=response['Marker'])
                            attached_policies += response['AttachedPolicies']
                        group['Policies'] += attached_policies
                    except ClientError as error:
                        print('    List attached group policies failed')
                        if error.response['Error']['Code'] == 'AccessDenied':
                            print(
                                '      FAILURE: MISSING REQUIRED AWS PERMISSIONS'
                            )
                        else:
                            print('      {}'.format(
                                error.response['Error']['Code']))
                        user['PermissionsConfirmed'] = False
                    user = parse_attached_policies(client, attached_policies,
                                                   user)

                # Get inline user policies
                policies = []
                if 'Policies' not in user:
                    user['Policies'] = []
                try:
                    response = client.list_user_policies(
                        UserName=user['UserName'])
                    policies = response['PolicyNames']
                    while 'IsTruncated' in response and response[
                            'IsTruncated'] is True:
                        response = client.list_user_policies(
                            UserName=user['UserName'],
                            Marker=response['Marker'])
                        policies += response['PolicyNames']
                    for policy in policies:
                        user['Policies'].append({'PolicyName': policy})
                except ClientError as error:
                    print('    List user policies failed')
                    if error.response['Error']['Code'] == 'AccessDenied':
                        print(
                            '      FAILURE: MISSING REQUIRED AWS PERMISSIONS')
                    else:
                        print('      {}'.format(
                            error.response['Error']['Code']))
                    user['PermissionsConfirmed'] = False

                # Get document for each inline policy
                for policy in policies:
                    try:
                        document = client.get_user_policy(
                            UserName=user['UserName'],
                            PolicyName=policy)['PolicyDocument']
                    except ClientError as error:
                        print('    Get user policy failed')
                        if error.response['Error']['Code'] == 'AccessDenied':
                            print(
                                '      FAILURE: MISSING REQUIRED AWS PERMISSIONS'
                            )
                        else:
                            print('      {}'.format(
                                error.response['Error']['Code']))
                        user['PermissionsConfirmed'] = False
                    user = parse_document(document, user)

                # Get attached user policies
                attached_policies = []
                try:
                    response = client.list_attached_user_policies(
                        UserName=user['UserName'])
                    attached_policies = response['AttachedPolicies']
                    while 'IsTruncated' in response and response[
                            'IsTruncated'] is True:
                        response = client.list_attached_user_policies(
                            UserName=user['UserName'],
                            Marker=response['Marker'])
                        attached_policies += response['AttachedPolicies']
                    user['Policies'] += attached_policies
                except ClientError as error:
                    print('    List attached user policies failed')
                    if error.response['Error']['Code'] == 'AccessDenied':
                        print(
                            '      FAILURE: MISSING REQUIRED AWS PERMISSIONS')
                    else:
                        print('      {}'.format(
                            error.response['Error']['Code']))
                    user['PermissionsConfirmed'] = False

                user = parse_attached_policies(client, attached_policies, user)
                if user['PermissionsConfirmed']:
                    summary_data['users_confirmed'] += 1

                if args.user_name is None and args.all_users is False:
                    print('    Confirmed Permissions for {}'.format(
                        user['UserName']))
                    active_aws_key.update(
                        pacu_main.database,
                        user_name=user['UserName'],
                        arn=user['Arn'],
                        user_id=user['UserId'],
                        groups=user['Groups'],
                        policies=user['Policies'],
                        permissions_confirmed=user['PermissionsConfirmed'],
                        allow_permissions=user['Permissions']['Allow'],
                        deny_permissions=user['Permissions']['Deny'])
                else:
                    with save(
                            'confirmed_permissions/user-{}.json'.format(
                                session.name, user['UserName']), 'w+') as f:
                        json.dump(user, f, indent=2, default=str)

                    print('    Permissions stored in user-{}.json'.format(
                        user['UserName']))
            except ClientError as error:
                if error.response['Error']['Code'] == 'AccessDenied':
                    print('  FAILURE: MISSING REQUIRED AWS PERMISSIONS')
                else:
                    print('  {}'.format(error.response['Error']['Code']))
                print('Skipping {}'.format(user['UserName']))

    return summary_data
def main(args, pacu_main: 'Main'):
    session = pacu_main.get_active_session()

    args = parser.parse_args(args)
    print = pacu_main.print

    get_regions = pacu_main.get_regions

    summary_data = {"SecretsManager": 0, "ParameterStore": 0}

    if args.regions is None:
        regions = get_regions('secretsmanager')
        if regions is None or regions == [] or regions == '' or regions == {}:
            print(
                'This module is not supported in any regions specified in the current sessions region set. Exiting...'
            )
            return None
    else:
        regions = args.regions.split(',')

    if args.secrets_manager is False and args.parameter_store is False:
        args.secrets_manager = args.parameter_store = True

    all_secrets_ids_sm = []
    all_secrets_ids_ssm = []

    for region in regions:
        secret_ids = []
        secrets_ssm = []

        print('Starting region {}...'.format(region))
        if args.secrets_manager:
            client = pacu_main.get_boto3_client('secretsmanager', region)

            response = None
            next_token = False
            while (response is None) or 'NextToken' in response:
                if next_token is False:
                    try:
                        response = client.list_secrets()
                    except ClientError as error:
                        code = error.response['Error']['Code']
                        print('FAILURE: ')
                        if code == 'UnauthorizedOperation':
                            print('  Access denied to ListSecrets.')
                        else:
                            print('  ' + code)
                        print('    Could not list secrets... Exiting')
                        response = None
                        break
                    except EndpointConnectionError as error:
                        print(
                            '    Error connecting to SecretsManager Endpoint for listing secrets for region: {}'
                            .format(region))
                        print('        Error: {}, {}'.format(
                            error.__class__, str(error)))
                        response = None
                        break
                    except Exception as error:
                        print(
                            '    Generic Error when Listing SecretsManager for region: {}'
                            .format(region))
                        print('        Error: {}, {}'.format(
                            error.__class__, str(error)))
                        response = None
                        break

                else:
                    response = client.list_secrets()

                if response:
                    for secret in response['SecretList']:
                        secret_ids.append({
                            "name": secret["Name"],
                            "region": region
                        })

            all_secrets_ids_sm += secret_ids

        for sec in all_secrets_ids_sm:
            secret_values = []
            client = pacu_main.get_boto3_client('secretsmanager',
                                                sec["region"])

            response = None
            while response is None:
                try:
                    response = client.get_secret_value(SecretId=sec["name"])
                except ClientError as error:
                    code = error.response['Error']['Code']
                    print('FAILURE: ')
                    if code == 'UnauthorizedOperation':
                        print('  Access denied to GetSecretsValue.')
                    else:
                        print(' ' + code)
                    print('    Could not get secrets value... Exiting')
                    response = None
                    break
                except EndpointConnectionError as error:
                    print(
                        '    Error connecting to SecretsManager Endpoint for getting secret for region: {}'
                        .format(sec["region"]))
                    print('        Error: {}, {}'.format(
                        error.__class__, str(error)))
                    response = None
                    break
                except Exception as error:
                    print(
                        '    Generic Error when getting Secret from Secrets Manager for region: {}'
                        .format(sec["region"]))
                    print('        Error: {}, {}'.format(
                        error.__class__, str(error)))
                    response = None
                    break

            if response:
                with save('secrets/secrets_manager/secrets.txt', 'a') as f:
                    f.write("{}:{}\n".format(sec["name"],
                                             response["SecretString"]))

        if args.parameter_store:
            client = pacu_main.get_boto3_client('ssm', region)

            response = None
            while response is None:
                try:
                    response = client.describe_parameters()
                except ClientError as error:
                    code = error.response['Error']['Code']
                    print('FAILURE: ')
                    if code == 'UnauthorizedOperation':
                        print('  Access denied to DescribeParameters.')
                    else:
                        print(' ' + code)
                    print('    Could not list parameters... Exiting')
                    response = None
                    break
                except EndpointConnectionError as error:
                    print(
                        '    Error connecting to SSM Endpoint for describing SSM Parameters for region: {}'
                        .format(region))
                    print('        Error: {}, {}'.format(
                        error.__class__, str(error)))
                    response = None
                    break
                except Exception as error:
                    print(
                        '    Generic Error when describing SSM Parameters for region: {}'
                        .format(region))
                    print('        Error: {}, {}'.format(
                        error.__class__, str(error)))
                    response = None
                    break

                if response:
                    for param in response["Parameters"]:
                        secrets_ssm.append({
                            "name": param["Name"],
                            "type": param["Type"],
                            "region": region
                        })

            all_secrets_ids_ssm += secrets_ssm

            for param in all_secrets_ids_ssm:
                client = pacu_main.get_boto3_client('ssm', param["region"])

                response = None
                while response is None:
                    if param["type"] != "SecureString":
                        try:
                            response = client.get_parameter(Name=param["name"])
                        except ClientError as error:
                            code = error.response['Error']['Code']
                            print('FAILURE: ')
                            if code == 'UnauthorizedOperation':
                                print('  Access denied to GetParameter.')
                            else:
                                print(' ' + code)
                            print(
                                '    Could not get parameter value... Exiting')
                            response = None
                            break
                        except EndpointConnectionError as error:
                            print(
                                '    Error connecting to SSM Endpoint for describing SSM '
                                'Secure parameter for region: {}'.format(
                                    param["region"]))
                            print('        Error: {}, {}'.format(
                                error.__class__, str(error)))
                            response = None
                        except Exception as error:
                            print(
                                '    Generic Error when describing SSM Secure Parameter '
                                'for region: {}'.format(param['region']))
                            print('        Error: {}, {}'.format(
                                error.__class__, str(error)))
                            response = None
                            break

                    else:
                        try:
                            response = client.get_parameter(
                                Name=param["name"], WithDecryption=True)
                        except ClientError as error:
                            code = error.response['Error']['Code']
                            print('FAILURE: ')
                            if code == 'UnauthorizedOperation':
                                print('  Access denied to GetParameter.')
                            else:
                                print(' ' + code)
                            print(
                                '    Could not get parameter value... Exiting')
                            response = None
                            break
                        except EndpointConnectionError as error:
                            print(
                                '    Error connecting to SSM Endpoint for describing '
                                'SSM parameter for region: {}'.format(
                                    param["region"]))
                            print('        Error: {}, {}'.format(
                                error.__class__, str(error)))
                            response = None
                            break
                        except Exception as error:
                            print(
                                '    Generic Error when describing SSM Parameter for region: {}'
                                .format(param['region']))
                            print('        Error: {}, {}'.format(
                                error.__class__, str(error)))
                            response = None
                            break

                    if response:
                        with save('secrets/parameter_store/parameters.txt',
                                  'a') as f:
                            f.write("{}:{}\n".format(
                                param["name"], response["Parameter"]["Value"]))

    summary_data["SecretsManager"] = len(all_secrets_ids_sm)
    summary_data["ParameterStore"] = len(all_secrets_ids_ssm)

    # Make sure your main function returns whatever data you need to construct
    # a module summary string.
    return summary_data
Example #11
0
def main(args, pacu_main: 'Main'):
    session = pacu_main.get_active_session()

    ###### Don't modify these. They can be removed if you are not using the function.
    args = parser.parse_args(args)
    print = pacu_main.print

    fetch_data = pacu_main.fetch_data
    ######

    instances = []
    templates = []
    summary_data = {'instance_downloads': 0, 'template_downloads': 0}

    if args.instance_ids is not None:
        for instance in args.instance_ids.split(','):
            instance_id, region = instance.split('@')
            instances.append({'InstanceId': instance_id, 'Region': region})
    elif args.template_ids is None:
        # If args.instance_ids was not passed in,
        # only fetch instances if args.template_ids
        # is also None
        if fetch_data(['EC2', 'Subnets'],
                      module_info['prerequisite_modules'][0],
                      '--instances') is False:
            print('Pre-req module not run successfully. Exiting...')
            return None
        instances = session.EC2['Instances']

    if args.template_ids is not None:
        for template in args.template_ids.split(','):
            template_id, region = template.split('@')
            templates.append({
                'LaunchTemplateId': template_id,
                'Region': region
            })
    elif args.instance_ids is None:
        # If args.template_ids was not passed in,
        # only fetch templates if args.instance_ids
        # is also None
        if fetch_data(['EC2', 'LaunchTemplates'],
                      module_info['prerequisite_modules'][0],
                      '--launch-templates') is False:
            print('Pre-req module not run successfully. Exiting...')
            templates = []
        else:
            templates = session.EC2['LaunchTemplates']

    if instances:
        print('Targeting {} instance(s)...'.format(len(instances)))
        for instance in instances:

            # if the filter is actived check the tags. If tags do not match skip instance
            if args.filter and not has_tags(args.filter.split(','), instance):
                continue

            instance_id = instance['InstanceId']
            region = instance['Region']
            client = pacu_main.get_boto3_client('ec2', region)

            try:
                user_data = client.describe_instance_attribute(
                    InstanceId=instance_id, Attribute='userData')['UserData']
            except ClientError as error:
                code = error.response['Error']['Code']
                print('FAILURE: ')
                if code == 'AccessDenied':
                    print('  Access denied to DescribeInstanceAttribute.')
                    print('Skipping the rest of the instances...')
                    break
                else:
                    print('  ' + code)

            if 'Value' in user_data.keys():
                decoded = base64.b64decode(user_data['Value'])

                try:
                    decompressed = gzip.decompress(decoded)
                    formatted_user_data = '{}@{}:\n{}\n\n'.format(
                        instance_id, region,
                        decompressed.decode('utf-8', 'backslashreplace'))
                except:
                    formatted_user_data = '{}@{}:\n{}\n\n'.format(
                        instance_id, region,
                        decoded.decode('utf-8', 'backslashreplace'))

                print('  {}@{}: User Data found'.format(instance_id, region))

                # Check for secrets
                find_secrets(formatted_user_data)

                # Write to the "all" file
                with save('ec2_user_data/all_user_data.txt', 'a+') as f:
                    f.write(formatted_user_data)
                # Write to the individual file
                with save('ec2_user_data/{}.txt'.format(instance_id)) as f:
                    f.write(
                        formatted_user_data.replace('\\t', '\t').replace(
                            '\\n', '\n').rstrip())
                summary_data['instance_downloads'] += 1
            else:
                print('  {}@{}: No User Data found'.format(
                    instance_id, region))
        print()
    else:
        print('No instances to target.\n')

    if templates:
        print('Targeting {} launch template(s)...'.format(len(templates)))
        for template in templates:
            template_id = template['LaunchTemplateId']
            region = template['Region']
            client = pacu_main.get_boto3_client('ec2', region)

            all_versions = []

            try:
                response = client.describe_launch_template_versions(
                    LaunchTemplateId=template_id)
                all_versions.extend(response['LaunchTemplateVersions'])
            except ClientError as error:
                code = error.response['Error']['Code']
                print('FAILURE: ')
                if code == 'AccessDenied':
                    print('  Access denied to DescribeLaunchTemplateVersions.')
                    print('Skipping the rest of the launch templates...\n')
                    break
                else:
                    print('  ' + code)

            while response.get('NextToken'):
                response = client.describe_launch_template_versions(
                    LaunchTemplateId=template_id,
                    NextToken=response['NextToken'])
                all_versions.extend(response['LaunchTemplateVersions'])

            for version in all_versions:
                if version['LaunchTemplateData'].get('UserData'):
                    try:
                        was_unzipped = False
                        user_data = version['LaunchTemplateData']['UserData']
                        formatted_user_data = '{}-version-{}@{}:\n{}\n\n'.format(
                            template_id, version['VersionNumber'], region,
                            base64.b64decode(user_data).decode('utf-8'))
                    except UnicodeDecodeError as error:
                        try:
                            decoded = base64.b64decode(user_data)
                            decompressed = gzip.decompress(decoded)
                            formatted_user_data = '{}@{}:\n{}\n\n'.format(
                                instance_id, region,
                                decompressed.decode('utf-8'))
                            was_unzipped = True
                        except:
                            print('ERROR: GZIP decrompressing template data')
                    print('  {}-version-{}@{}: User Data found'.format(
                        template_id, version['VersionNumber'], region))
                    if was_unzipped:
                        print('    Gzip decoded the User Data')

                    # Write to the "all" file
                    with save('ec2_user_data/all_user_data.txt', 'a+') as f:
                        f.write(formatted_user_data)
                    # Write to the individual file
                    with save('ec2_user_data/{}-version-{}.txt'.format(
                            template_id, version['VersionNumber'])) as f:
                        f.write(
                            formatted_user_data.replace('\\t', '\t').replace(
                                '\\n', '\n').rstrip())
                    summary_data['template_downloads'] += 1
                else:
                    print('  {}-version-{}@{}: No User Data found'.format(
                        template_id, version['VersionNumber'], region))
        print()
    else:
        print('No launch templates to target.\n')

    return summary_data
Example #12
0
def main(args, pacu_main: 'Main'):
    session = pacu_main.get_active_session()

    ###### Don't modify these. They can be removed if you are not using the function.
    args = parser.parse_args(args)
    print = pacu_main.print
    input = pacu_main.input

    key_info = pacu_main.key_info
    get_regions = pacu_main.get_regions
    ######

    if args.snaps is False and args.vols is False:
        args.snaps = args.vols = True

    ec2_data = deepcopy(session.EC2)
    if 'Volumes' not in ec2_data.keys():
        ec2_data['Volumes'] = []
    if 'Snapshots' not in ec2_data.keys():
        ec2_data['Snapshots'] = []
    session.update(pacu_main.database, EC2=ec2_data)

    if args.regions is None:
        regions = get_regions('ec2')
        if regions is None or regions == [] or regions == '' or regions == {}:
            print(
                'This module is not supported in any regions specified in the current sessions region set. Exiting...'
            )
            return
    else:
        regions = args.regions.split(',')

    account_ids = []

    if args.account_ids is None and args.snaps is True:
        user = key_info()

        if 'AccountId' in user and user['AccountId'] is not None:
            account_ids = [user['AccountId']]
        else:
            current_account = input(
                strip_lines('''
                No account IDs were passed in as arguments and the account ID for the current user has not been stored 
                in this session yet. An account ID is required to get valid results from the snapshot enumeration 
                portion of this module. If you know the current users account ID then enter it now, otherwise, enter 
                y to try and fetch it, or enter n to skip EBS snapshot enumeration. ([account_id]/y/n)
            '''))

            if current_account is None or current_account == '' or current_account.lower(
            ) == 'n':
                account_ids = []

            elif current_account == 'y':
                try:
                    client = pacu_main.get_boto3_client('sts')

                    identity = client.get_caller_identity()

                    account_ids = [identity['Account']]

                    # Might as well fill current key data while it is here
                    session_aws_key = session.get_active_aws_key(
                        pacu_main.database)
                    session_aws_key.update(
                        pacu_main.database,
                        account_id=identity['Account'],
                        arn=identity['Arn'],
                        user_id=identity['UserId'],
                    )
                except Exception as error:
                    print(
                        'Error running sts.get_caller_identity. It is possible that the account ID has been returned '
                        'in this error: {}'.format(error))
                    current_account = input(
                        'If the AWS account ID was returned in the previous error, enter it now to '
                        'continue, or enter n to skip EBS snapshot enumeration. ([account_id]/n) '
                    )
                    if current_account == 'n':
                        account_ids = []
                    else:
                        account_ids = [current_account]

            else:
                account_ids = [current_account]

    elif args.snaps is True:
        account_ids = args.account_ids.split(',')

    else:
        pass  # Ignore args.account_ids if args.snaps is False

    client = pacu_main.get_boto3_client('ec2', random.choice(regions))

    now = time.time()

    all_vols = []
    all_snaps = []
    volumes_csv_data = []
    snapshots_csv_data = []
    snapshot_permissions = {'Public': [], 'Shared': {}, 'Private': []}
    for region in regions:
        print(
            'Starting region {} (this may take a while if there are thousands of EBS volumes/snapshots)...'
            .format(region))
        client = pacu_main.get_boto3_client('ec2', region)

        if args.vols is True:
            # Start EBS Volumes in this region
            count = 0
            response = None
            next_token = False

            while (response is None or 'NextToken' in response):
                if next_token is False:
                    try:
                        response = client.describe_volumes(
                            MaxResults=
                            500  # Using this as AWS can timeout the connection if there are too many volumes to return in one
                        )
                    except ClientError as error:
                        code = error.response['Error']['Code']
                        print('FAILURE: ')
                        if code == 'UnauthorizedOperation':
                            print('  Access denied to DescribeVolumes.')
                        else:
                            print('  ' + code)
                        print('Skipping volume enumeration...')
                        break
                else:
                    response = client.describe_volumes(MaxResults=500,
                                                       NextToken=next_token)

                if 'NextToken' in response:
                    next_token = response['NextToken']

                for volume in response['Volumes']:
                    volume['Region'] = region
                    all_vols.append(volume)
                    if volume['Encrypted'] is False:
                        name = ''
                        if 'Tags' in volume:
                            for tag in volume['Tags']:
                                if tag['Key'] == 'Name':
                                    name = tag['Value']
                                    break
                        volumes_csv_data.append('{},{},{}\n'.format(
                            name, volume['VolumeId'], region))

                count += len(response['Volumes'])

            print('    {} volume(s) found'.format(count))

        if args.snaps is True and not account_ids == []:
            # Start EBS Snapshots in this region
            count = 0
            response = None
            next_token = False

            while (response is None or 'NextToken' in response):
                if next_token is False:
                    try:
                        response = client.describe_snapshots(
                            OwnerIds=account_ids,
                            MaxResults=
                            1000  # Using this as AWS can timeout the connection if there are too many snapshots to return in one
                        )
                    except ClientError as error:
                        code = error.response['Error']['Code']
                        print('FAILURE: ')
                        if code == 'UnauthorizedOperation':
                            print('  Access denied to DescribeSnapshots.')
                        else:
                            print('  ' + code)
                        print('Skipping snapshot enumeration...')
                        break
                else:
                    response = client.describe_snapshots(OwnerIds=account_ids,
                                                         NextToken=next_token,
                                                         MaxResults=1000)

                if 'NextToken' in response:
                    next_token = response['NextToken']

                for snapshot in response['Snapshots']:
                    snapshot['Region'] = region

                    if args.snapshot_permissions:
                        print(
                            '    Starting enumeration for Snapshot Permissions...'
                        )
                        snapshot[
                            'CreateVolumePermissions'] = client.describe_snapshot_attribute(
                                Attribute='createVolumePermission',
                                SnapshotId=snapshot['SnapshotId']
                            )['CreateVolumePermissions']

                        if not snapshot['CreateVolumePermissions']:
                            snapshot_permissions['Private'].append(
                                snapshot['SnapshotId'])
                        elif 'UserId' in snapshot['CreateVolumePermissions'][
                                0]:
                            snapshot_permissions['Shared'][
                                snapshot['SnapshotId']] = [
                                    entry['UserId'] for entry in
                                    snapshot['CreateVolumePermissions']
                                ]
                        elif 'Group' in snapshot['CreateVolumePermissions'][0]:
                            snapshot_permissions['Public'].append(
                                snapshot['SnapshotId'])

                    all_snaps.append(snapshot)
                    if snapshot['Encrypted'] is False:
                        name = ''
                        if 'Tags' in snapshot:
                            for tag in snapshot['Tags']:
                                if tag['Key'] == 'Name':
                                    name = tag['Value']
                                    break
                        snapshots_csv_data.append('{},{},{}\n'.format(
                            name, snapshot['SnapshotId'], region))

                count += len(response['Snapshots'])

            print('    {} snapshot(s) found'.format(count))

    summary_data = {'snapshot_permissions': args.snapshot_permissions}
    if args.vols:
        ec2_data['Volumes'] = all_vols
        summary_data['volumes'] = len(ec2_data['Volumes'])
        p = 'unencrypted_ebs_volumes_{}.csv'.format(now)
        with save(p) as f:
            f.write('Volume Name,Volume ID,Region\n')
            print('  Writing data for {} volumes...'.format(
                len(volumes_csv_data)))
            for line in volumes_csv_data:
                f.write(line)
        summary_data['volumes_csv_path'] = p

    if args.snaps:
        ec2_data['Snapshots'] = all_snaps
        summary_data['snapshots'] = len(ec2_data['Snapshots'])
        path = 'unencrypted_ebs_snapshots_{}.csv'.format(now)
        with save(path) as f:
            f.write('Snapshot Name,Snapshot ID,Region\n')
            print('  Writing data for {} snapshots...'.format(
                len(snapshots_csv_data)))
            for line in snapshots_csv_data:
                f.write(line)
        summary_data['snapshots_csv_path'] = path

    if args.snapshot_permissions:
        permission_data = {
            'Public': len(snapshot_permissions['Public']),
            'Shared': len(snapshot_permissions['Shared']),
            'Private': len(snapshot_permissions['Private']),
        }
        temp = permission_data.copy()
        summary_data.update(temp)
        path = 'snapshot_permissions_' + str(now) + '.txt'
        with save(path) as f:
            f.write('Public:\n')
            for public in snapshot_permissions['Public']:
                f.write('    {}'.format(public))
            f.write('Shared:\n')
            for snap in snapshot_permissions['Shared']:
                f.write('    {}\n'.format(snap))
                for aws_id in snapshot_permissions['Shared'][snap]:
                    f.write('        {}\n'.format(aws_id))
            f.write('Private:\n')
            for private in snapshot_permissions['Private']:
                f.write('    {}\n'.format(private))
            summary_data['snapshot-permissions-path'] = path
    session.update(pacu_main.database, EC2=ec2_data)

    return summary_data
Example #13
0
def main(args, pacu_main: 'Main'):
    session = pacu_main.get_active_session()

    ###### Don't modify these. They can be removed if you are not using the function.
    args = parser.parse_args(args)
    print = pacu_main.print
    input = pacu_main.input
    ######

    client = pacu_main.get_boto3_client('iam')
    report = None
    generated = False
    summary_data = {'generated': False}
    while True:
        try:
            report = client.get_credential_report()
            break
        except ClientError as error:
            code = error.response['Error']['Code']
            if code == 'ReportNotPresent' or code == 'ReportInProgress':
                if generated or code == 'ReportInProgress':
                    generated = True
                    print('waiting...')
                    time.sleep(20)
                else:
                    generate = input('Report not found. Generate? (y/n) ')
                    if generate == 'y':
                        try:
                            client.generate_credential_report()
                            print(
                                '  Starting. Checking completion every 20 seconds...'
                            )
                            generated = True
                            summary_data['generated'] = True
                        except ClientError as error:
                            if error.response['Error'][
                                    'Code'] == 'AccessDenied':
                                print(
                                    'Unauthorized to generate_credential_report'
                                )
                                report = None
                                break
                    else:
                        report = None
                        break
            elif code == 'AccessDenied':
                print('  FAILURE:')
                print('    MISSING NEEDED PERMISSIONS')
                report = None
                break
            else:
                print('Unrecognized ClientError: {} ({})'.format(
                    str(error), error.response['Error']['Code']))
                break

    if report and 'Content' in report:
        filename = 'downloads/get_credential_report_{}.csv'.format(
            session.name, time.time())
        save(report['Content'].decode(), filename)
        summary_data['report_location'] = filename
        print('Credential report saved to {}'.format(filename))

    else:
        print('\n  Unable to generate report.')

    return summary_data