def StartAnalysisVm(args: 'argparse.Namespace') -> None: """Start forensic analysis VM. Args: args (argparse.Namespace): Arguments from ArgumentParser. """ if args.attach_volumes and len(args.attach_volumes.split(',')) > 11: logger.error('--attach_volumes must be < 11') return attach_volumes = [] if args.attach_volumes: volumes = args.attach_volumes.split(',') # Check if volumes parameter exists and if there # are any empty entries. if not (volumes and all(elements for elements in volumes)): logger.error('parameter --attach_volumes: {0:s}'.format( args.attach_volumes)) return # AWS recommends using device names that are within /dev/sd[f-p]. device_letter = ord('f') for volume in volumes: attach = (volume, '/dev/sd'+chr(device_letter)) attach_volumes.append(attach) device_letter = device_letter + 1 key_name = args.ssh_key_name if args.generate_ssh_key_pair: logger.info('Generating SSH key pair for the analysis VM.') aws_account = account.AWSAccount(args.zone) key_name, private_key = aws_account.ec2.GenerateSSHKeyPair( args.instance_name) path = os.path.join(os.getcwd(), key_name + '.pem') with open(path, 'w') as f: f.write(private_key) logger.info( 'Created key pair {0:s} in AWS. Your private key is saved in: ' '{1:s}'.format(key_name, path)) logger.info('Starting analysis VM...') vm = forensics.StartAnalysisVm(vm_name=args.instance_name, default_availability_zone=args.zone, boot_volume_size=int(args.boot_volume_size), boot_volume_type=args.boot_volume_type, cpu_cores=int(args.cpu_cores), ami=args.ami, ssh_key_name=key_name, attach_volumes=attach_volumes, dst_profile=args.dst_profile) logger.info('Analysis VM started.') logger.info('Name: {0:s}, Started: {1:s}, Region: {2:s}'.format(vm[0].name, str(vm[1]), vm[0].region))
def setUpClass(cls): try: project_info = utils.ReadProjectInfo(['instance', 'zone']) except (OSError, RuntimeError, ValueError) as exception: raise unittest.SkipTest(str(exception)) cls.instance_to_analyse = project_info['instance'] cls.zone = project_info['zone'] cls.dst_zone = project_info.get('destination_zone', None) cls.volume_to_copy = project_info.get('volume_id', None) cls.encrypted_volume_to_copy = project_info.get('encrypted_volume_id', None) cls.aws = account.AWSAccount(cls.zone) cls.analysis_vm_name = 'new-vm-for-analysis' cls.analysis_vm, _ = forensics.StartAnalysisVm(cls.analysis_vm_name, cls.zone, 10) cls.volumes = [] # List of (AWSAccount, AWSVolume) tuples
def StartAnalysisVm(args: 'argparse.Namespace') -> None: """Start forensic analysis VM. Args: args (argparse.Namespace): Arguments from ArgumentParser. """ if args.attach_volumes and len(args.attach_volumes.split(',')) > 11: print('error: --attach_volumes must be < 11') return attach_volumes = [] if args.attach_volumes: volumes = args.attach_volumes.split(',') # Check if volumes parameter exists and if there # are any empty entries. if not (volumes and all(elements for elements in volumes)): print('error: parameter --attach_volumes: {0:s}'.format(args.attach_volumes)) return # AWS recommends using device names that are within /dev/sd[f-p]. device_letter = ord('f') for volume in volumes: attach = (volume, '/dev/sd'+chr(device_letter)) attach_volumes.append(attach) device_letter = device_letter + 1 print('Starting analysis VM...') vm = forensics.StartAnalysisVm(vm_name=args.instance_name, default_availability_zone=args.zone, boot_volume_size=int(args.boot_volume_size), cpu_cores=int(args.cpu_cores), ami=args.ami, ssh_key_name=args.ssh_key_name, attach_volumes=attach_volumes, dst_profile=args.dst_profile) print('Analysis VM started.') print('Name: {0:s}, Started: {1:s}, Region: {2:s}'.format(vm[0].name, str(vm[1]), vm[0].region))
def testStartVm(self): """End to end test on AWS. Test creating an analysis VM and attaching a copied volume to it. """ volume_copy = forensics.CreateVolumeCopy(self.zone, volume_id=self.volume_to_copy) self.volumes.append((self.aws, volume_copy)) # Create and start the analysis VM and attach the boot volume self.analysis_vm, _ = forensics.StartAnalysisVm( self.analysis_vm_name, self.zone, 10, attach_volumes=[(volume_copy.volume_id, '/dev/sdp')]) # The forensic instance should be live in the analysis AWS account and # the volume should be attached instance = self.aws.ResourceApi(EC2_SERVICE).Instance( self.analysis_vm.instance_id) self.assertEqual(instance.instance_id, self.analysis_vm.instance_id) self.assertIn(volume_copy.volume_id, [vol.volume_id for vol in instance.volumes.all()])
def SetUp(self, remote_profile_name, remote_zone, incident_id, remote_instance_id=None, volume_ids=None, all_volumes=False, analysis_profile_name=None, analysis_zone=None, boot_volume_size=50, cpu_cores=16, ami=None): """Sets up an Amazon web Services (AWS) collector. This method creates and starts an analysis VM in the AWS account and selects volumes to copy from the target instance / list of volumes passed in parameter. If volume_ids is specified, it will copy the corresponding volumes from the account, ignoring volumes belonging to any specific instances. If remote_instance_id is specified, two behaviors are possible: * If no other parameters are specified, it will select the instance's boot volume. * if all_volumes is set to True, it will select all volumes in the account that are attached to the instance. volume_ids takes precedence over remote_instance_id. Args: remote_profile_name (str): The AWS account in which the volume(s) exist(s). This is the profile name that is defined in your AWS credentials file. remote_zone (str): The AWS zone in which the source volume(s) exist(s). incident_id (str): Incident identifier used to name the analysis VM. remote_instance_id (str): Optional. Instance ID that needs forensicating. volume_ids (str): Optional. Comma-separated list of volume ids to copy. all_volumes (bool): Optional. True if all volumes attached to the source instance should be copied. analysis_profile_name (str): Optional. The AWS account in which to create the analysis VM. This is the profile name that is defined in your AWS credentials file. analysis_zone (str): Optional. The AWS zone in which to create the VM. If not specified, the VM will be created in the same zone where the volume(s) exist(s). boot_volume_size (int): Optional. The size (in GB) of the boot volume for the analysis VM. Default is 50 GB. cpu_cores (int): Optional. The number of CPU cores to use for the analysis VM. Default is 16. ami (str): Optional. The Amazon Machine Image ID to use to create the analysis VM. If not specified, will default to selecting Ubuntu 18.04 TLS. """ if not (remote_instance_id or volume_ids): self.ModuleError( 'You need to specify at least an instance name or volume ids to copy', critical=True) return if not (remote_profile_name and remote_zone): self.ModuleError('You must specify "remote_profile_name" and "zone" ' 'parameters', critical=True) return self.remote_profile_name = remote_profile_name self.remote_zone = remote_zone self.source_account = aws_account.AWSAccount( self.remote_zone, aws_profile=self.remote_profile_name) self.incident_id = incident_id self.remote_instance_id = remote_instance_id self.volume_ids = volume_ids.split(',') if volume_ids else [] self.all_volumes = all_volumes self.analysis_zone = analysis_zone or remote_zone self.analysis_profile_name = analysis_profile_name or remote_profile_name analysis_vm_name = 'aws-forensics-vm-{0:s}'.format(self.incident_id) print('Your analysis VM will be: {0:s}'.format(analysis_vm_name)) self.state.StoreContainer( containers.TicketAttribute( name=self._ANALYSIS_VM_CONTAINER_ATTRIBUTE_NAME, type_=self._ANALYSIS_VM_CONTAINER_ATTRIBUTE_TYPE, value=analysis_vm_name)) self.analysis_vm, _ = aws_forensics.StartAnalysisVm( analysis_vm_name, self.analysis_zone, boot_volume_size, ami=ami, cpu_cores=cpu_cores, dst_profile=self.analysis_profile_name, )