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
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
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
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
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
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
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
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
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
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
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
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