diff --git a/dftimewolf/lib/collectors/aws.py b/dftimewolf/lib/collectors/aws.py index 8a605459..da964dbe 100644 --- a/dftimewolf/lib/collectors/aws.py +++ b/dftimewolf/lib/collectors/aws.py @@ -70,7 +70,7 @@ def __init__(self, def Process(self) -> None: """Copies a volume and attaches it to the analysis VM.""" for volume in self._FindVolumesToCopy(): - print('Volume copy of {0:s} started...'.format(volume.volume_id)) + print(f'Volume copy of {volume.volume_id:s} started...') new_volume = aws_forensics.CreateVolumeCopy( self.remote_zone, dst_zone=self.analysis_zone, @@ -168,8 +168,8 @@ def SetUp(self, 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)) + analysis_vm_name = f'aws-forensics-vm-{self.incident_id:s}' + print(f'Your analysis VM will be: {analysis_vm_name:s}') self.state.StoreContainer( containers.TicketAttribute( name=self._ANALYSIS_VM_CONTAINER_ATTRIBUTE_NAME, diff --git a/dftimewolf/lib/collectors/aws_logging.py b/dftimewolf/lib/collectors/aws_logging.py index edc1314e..3e74724c 100644 --- a/dftimewolf/lib/collectors/aws_logging.py +++ b/dftimewolf/lib/collectors/aws_logging.py @@ -59,7 +59,7 @@ def Process(self) -> None: output_file = tempfile.NamedTemporaryFile( mode='w', delete=False, encoding='utf-8', suffix='.jsonl') output_path = output_file.name - self.logger.info('Downloading logs to {0:s}'.format(output_path)) + self.logger.info(f'Downloading logs to {output_path:s}') if self._profile_name: try: diff --git a/dftimewolf/lib/collectors/aws_snapshot_s3_copy.py b/dftimewolf/lib/collectors/aws_snapshot_s3_copy.py index cd2e8817..7b0e9c50 100644 --- a/dftimewolf/lib/collectors/aws_snapshot_s3_copy.py +++ b/dftimewolf/lib/collectors/aws_snapshot_s3_copy.py @@ -94,7 +94,7 @@ def SetUp(self, def PreProcess(self) -> None: """Set up for the snapshot copy operation.""" if not self.bucket_exists: - self.logger.info('Creating AWS bucket {0:s}'.format(self.bucket)) + self.logger.info(f'Creating AWS bucket {self.bucket:s}') create_bucket_args = {'Bucket': self.bucket} # us-east-1 is the default, but throws an error if actually specified. @@ -132,8 +132,8 @@ def Process(self, container: containers.AWSSnapshot) -> None: for h in result['hashes']: self.state.StoreContainer(containers.AWSS3Object(h)) except ResourceCreationError as exception: - self.ModuleError('Exception during copy operation: {0!s}'. - format(exception), critical=True) + self.ModuleError( + f'Exception during copy operation: {exception!s}', critical=True) def PostProcess(self) -> None: """Clean up afterwards.""" diff --git a/dftimewolf/lib/collectors/aws_volume_snapshot.py b/dftimewolf/lib/collectors/aws_volume_snapshot.py index 96cde642..77dc9d6d 100644 --- a/dftimewolf/lib/collectors/aws_volume_snapshot.py +++ b/dftimewolf/lib/collectors/aws_volume_snapshot.py @@ -61,16 +61,14 @@ def Process(self) -> None: snapshot_ids = [] try: # Snapshot taking is an asynchronous call, no need for threading - self.logger.info('Taking snapshots of volumes {0:s}'. - format(','.join(volumes))) + self.logger.info(f'Taking snapshots of volumes {",".join(volumes):s}') for volume in volumes: response = ec2.create_snapshot(VolumeId=volume) snapshot_ids.append(response['SnapshotId']) self.logger.info('Waiting for snapshot completion') ec2.get_waiter('snapshot_completed').wait(SnapshotIds=snapshot_ids) - self.logger.info('Snapshots complete: {0:s}'. - format(','.join(snapshot_ids))) + self.logger.info(f'Snapshots complete: {",".join(snapshot_ids):s}') except ec2.exceptions.ClientError as exception: self.ModuleError('Error encountered snapshotting volumes: {0!s}'. format(exception), critical=True) diff --git a/dftimewolf/lib/collectors/azure.py b/dftimewolf/lib/collectors/azure.py index 0e3d8570..5f7b61e9 100644 --- a/dftimewolf/lib/collectors/azure.py +++ b/dftimewolf/lib/collectors/azure.py @@ -67,7 +67,7 @@ def __init__(self, def Process(self) -> None: """Copies a disk to the analysis account.""" for disk in self._FindDisksToCopy(): - self.logger.info('Disk copy of {0:s} started...'.format(disk.name)) + self.logger.info(f'Disk copy of {disk.name:s} started...') new_disk = az_forensics.CreateDiskCopy( self.analysis_resource_group_name, disk_name=disk.name, @@ -168,8 +168,8 @@ def SetUp(self, self.analysis_region = analysis_region self.analysis_profile_name = analysis_profile_name or remote_profile_name - analysis_vm_name = 'azure-forensics-vm-{0:s}'.format(self.incident_id) - print('Your analysis VM will be: {0:s}'.format(analysis_vm_name)) + analysis_vm_name = f'azure-forensics-vm-{self.incident_id:s}' + print(f'Your analysis VM will be: {analysis_vm_name:s}') self.state.StoreContainer( containers.TicketAttribute( name=self._ANALYSIS_VM_CONTAINER_ATTRIBUTE_NAME, diff --git a/dftimewolf/lib/collectors/azure_logging.py b/dftimewolf/lib/collectors/azure_logging.py index 24214892..91f5a045 100644 --- a/dftimewolf/lib/collectors/azure_logging.py +++ b/dftimewolf/lib/collectors/azure_logging.py @@ -52,7 +52,7 @@ def Process(self) -> None: output_file = tempfile.NamedTemporaryFile( mode='w', delete=False, encoding='utf-8', suffix='.jsonl') output_path = output_file.name - self.logger.info('Downloading logs to {0:s}'.format(output_path)) + self.logger.info(f'Downloading logs to {output_path:s}') try: _, credentials = lcf_common.GetCredentials( diff --git a/dftimewolf/lib/collectors/bigquery.py b/dftimewolf/lib/collectors/bigquery.py index 4415026c..43439451 100644 --- a/dftimewolf/lib/collectors/bigquery.py +++ b/dftimewolf/lib/collectors/bigquery.py @@ -42,9 +42,9 @@ def SetUp(self, project_name: str, query: str, description: str) -> None: def Process(self) -> None: """Collects data from BigQuery.""" output_file = tempfile.NamedTemporaryFile( - mode="w", delete=False, encoding="utf-8", suffix=".jsonl") + mode='w', delete=False, encoding='utf-8', suffix='.jsonl') output_path = output_file.name - self.logger.info("Downloading results to {0:s}".format(output_path)) + self.logger.info(f'Downloading results to {output_path:s}') try: if self._project_name: @@ -53,20 +53,20 @@ def Process(self) -> None: bq_client = bigquery.Client() records = bq_client.query(self._query).to_dataframe().to_json( - orient="records", lines=True, date_format="iso") + orient='records', lines=True, date_format='iso') output_file.write(records) # pytype: disable=module-attr except google.cloud.exceptions.NotFound as exception: - self.ModuleError(f"Error accessing project: {exception!s}", + self.ModuleError(f'Error accessing project: {exception!s}', critical=True) # pytype: enable=module-attr except (google_auth_exceptions.DefaultCredentialsError) as exception: self.ModuleError( - "Something is wrong with your gcloud access token or " - "Application Default Credentials. Try running:\n " - "$ gcloud auth application-default login" + 'Something is wrong with your gcloud access token or ' + 'Application Default Credentials. Try running:\n ' + '$ gcloud auth application-default login' ) self.ModuleError(exception, critical=True) diff --git a/dftimewolf/lib/collectors/filesystem.py b/dftimewolf/lib/collectors/filesystem.py index c3eb842a..56448686 100644 --- a/dftimewolf/lib/collectors/filesystem.py +++ b/dftimewolf/lib/collectors/filesystem.py @@ -49,7 +49,7 @@ def Process(self) -> None: container = containers.File(os.path.basename(path), path) file_containers.append(container) else: - self.logger.warning('Path {0:s} does not exist'.format(path)) + self.logger.warning(f'Path {path:s} does not exist') if not file_containers: self.ModuleError( message='No valid paths collected, bailing', diff --git a/dftimewolf/lib/collectors/gcp_logging.py b/dftimewolf/lib/collectors/gcp_logging.py index 2ff81c51..80e6b2e6 100644 --- a/dftimewolf/lib/collectors/gcp_logging.py +++ b/dftimewolf/lib/collectors/gcp_logging.py @@ -60,7 +60,7 @@ def Process(self) -> None: output_file = tempfile.NamedTemporaryFile( mode='w', delete=False, encoding='utf-8', suffix='.jsonl') output_path = output_file.name - self.logger.info('Downloading logs to {0:s}'.format(output_path)) + self.logger.info(f'Downloading logs to {output_path:s}') try: if self._project_name: @@ -99,8 +99,8 @@ def Process(self) -> None: if not have_page and retries >= MAX_RETRIES: self.ModuleError( - 'Hit max retries ({0:d}) requesting GCP logs'.format( - MAX_RETRIES) , critical=True) + f'Hit max retries ({MAX_RETRIES:d}) requesting GCP logs', + critical=True) for entry in page: @@ -110,7 +110,7 @@ def Process(self) -> None: except google_api_exceptions.NotFound as exception: self.ModuleError( - 'Error accessing project: {0!s}'.format(exception), critical=True) + f'Error accessing project: {exception!s}', critical=True) except google_api_exceptions.InvalidArgument as exception: self.ModuleError( diff --git a/dftimewolf/lib/collectors/grr_base.py b/dftimewolf/lib/collectors/grr_base.py index e3182bf7..aca79148 100644 --- a/dftimewolf/lib/collectors/grr_base.py +++ b/dftimewolf/lib/collectors/grr_base.py @@ -114,7 +114,7 @@ def _WrapGRRRequestWithApproval( return grr_function(*args, **kwargs) except grr_errors.AccessForbiddenError as exception: - logger.info('No valid approval found: {0!s}'.format(exception)) + logger.info(f'No valid approval found: {exception!s}') # If approval was already sent, just wait a bit more. if approval_sent: logger.info('Approval not yet granted, waiting {0:d}s'.format( diff --git a/dftimewolf/lib/collectors/grr_hosts.py b/dftimewolf/lib/collectors/grr_hosts.py index 9c1034b2..914241d2 100644 --- a/dftimewolf/lib/collectors/grr_hosts.py +++ b/dftimewolf/lib/collectors/grr_hosts.py @@ -149,7 +149,7 @@ def _GetClientBySelector(self, selector: str) -> Client: DFTimewolfError: if no client ID found for selector. """ # Search for the selector in GRR - self.logger.info('Searching for client: {0:s}'.format(selector)) + self.logger.info(f'Searching for client: {selector:s}') try: search_result = self.grr_api.SearchClients(selector) except grr_errors.UnknownError as exception: @@ -160,8 +160,7 @@ def _GetClientBySelector(self, selector: str) -> Client: result = self._FilterSelectionCriteria(selector, search_result) if not result: - self.ModuleError('Could not get client for {0:s}'.format( - selector), critical=True) + self.ModuleError(f'Could not get client for {selector:s}', critical=True) active_clients = self._FilterActiveClients(result) if len(active_clients) >1: @@ -187,7 +186,7 @@ def _GetClientBySelector(self, selector: str) -> Client: datetime.datetime.utcnow() - last_seen_datetime).total_seconds() last_seen_minutes = int(round(last_seen_seconds / 60)) - self.logger.info('Found active client: {0:s}'.format(client.client_id)) + self.logger.info(f'Found active client: {client.client_id:s}') self.logger.info('Client last seen: {0:s} ({1:d} minutes ago)'.format( last_seen_datetime.strftime('%Y-%m-%dT%H:%M:%S+0000'), last_seen_minutes)) @@ -242,7 +241,7 @@ def _LaunchFlow(self, client: Client, name: str, args: str) -> str: keepalive_flow = client.CreateFlow( name='KeepAlive', args=flows_pb2.KeepAliveArgs()) self.logger.info( - 'KeepAlive Flow:{0:s} scheduled'.format(keepalive_flow.flow_id)) + f'KeepAlive Flow:{keepalive_flow.flow_id:s} scheduled') return flow_id @@ -257,7 +256,7 @@ def _AwaitFlow(self, client: Client, flow_id: str) -> None: Raises: DFTimewolfError: If a Flow error was encountered. """ - self.logger.info('{0:s}: Waiting to finish'.format(flow_id)) + self.logger.info(f'{flow_id:s}: Waiting to finish') if self.skip_offline_clients: self.logger.info('Client will be skipped if offline.') @@ -275,11 +274,10 @@ def _AwaitFlow(self, client: Client, flow_id: str) -> None: if 'ArtifactNotRegisteredError' in status.context.backtrace: message = status.context.backtrace.split('\n')[-2] raise DFTimewolfError( - '{0:s}: FAILED! Message from GRR:\n{1:s}'.format( - flow_id, message)) + f'{flow_id:s}: FAILED! Message from GRR:\n{message:s}') if status.state == flows_pb2.FlowContext.TERMINATED: - self.logger.info('{0:s}: Complete'.format(flow_id)) + self.logger.info(f'{flow_id:s}: Complete') break time.sleep(self._CHECK_FLOW_INTERVAL_SEC) @@ -337,7 +335,7 @@ def _DownloadFiles(self, client: Client, flow_id: str) -> Optional[str]: if os.path.exists(output_file_path): self.logger.info( - '{0:s} already exists: Skipping'.format(output_file_path)) + f'{output_file_path:s} already exists: Skipping') return None if is_timeline_flow: @@ -357,7 +355,7 @@ def _DownloadFiles(self, client: Client, flow_id: str) -> Optional[str]: shutil.copy2( output_file_path, os.path.join(client_output_folder, - '{}_timeline.body'.format(flow_id))) + f'{flow_id}_timeline.body')) else: with zipfile.ZipFile(output_file_path) as archive: archive.extractall(path=client_output_folder) @@ -483,13 +481,13 @@ def Process(self, container: containers.Host) -> None: """ for client in self._FindClients([container.hostname]): system_type = client.data.os_info.system - self.logger.info('System type: {0:s}'.format(system_type)) + self.logger.info(f'System type: {system_type:s}') # If the list is supplied by the user via a flag, honor that. artifact_list = [] if self.artifacts: self.logger.info( - 'Artifacts to be collected: {0!s}'.format(self.artifacts)) + f'Artifacts to be collected: {self.artifacts!s}') artifact_list = self.artifacts else: default_artifacts = self.artifact_registry.get(system_type, None) @@ -501,7 +499,7 @@ def Process(self, container: containers.Host) -> None: if self.extra_artifacts: self.logger.info( - 'Throwing in an extra {0!s}'.format(self.extra_artifacts)) + f'Throwing in an extra {self.extra_artifacts!s}') artifact_list.extend(self.extra_artifacts) artifact_list = list(set(artifact_list)) @@ -520,8 +518,8 @@ def Process(self, container: containers.Host) -> None: max_file_size=self.max_file_size) flow_id = self._LaunchFlow(client, 'ArtifactCollectorFlow', flow_args) if not flow_id: - msg = 'Flow could not be launched on {0:s}.'.format(client.client_id) - msg += '\nArtifactCollectorFlow args: {0!s}'.format(flow_args) + msg = f'Flow could not be launched on {client.client_id:s}.' + msg += f'\nArtifactCollectorFlow args: {flow_args!s}' self.ModuleError(msg, critical=True) self._AwaitFlow(client, flow_id) collected_flow_data = self._DownloadFiles(client, flow_id) @@ -624,7 +622,7 @@ def SetUp(self, if action.lower() in self._ACTIONS: self.action = self._ACTIONS[action.lower()] if self.action is None: - self.ModuleError("Invalid action {0!s}".format(action), + self.ModuleError(f"Invalid action {action!s}", critical=True) if max_file_size: self.max_file_size = int(max_file_size) @@ -672,8 +670,8 @@ def PreProcess(self) -> None: message = 'Would fetch 0 files - bailing out instead.' self.logger.critical(message) raise DFTimewolfError(message, critical=False) - self.logger.info('Filefinder to collect {0:d} items on each host'.format( - len(self.files))) + self.logger.info( + f'Filefinder to collect {len(self.files):d} items on each host') def PostProcess(self) -> None: """Check if we're skipping any offline clients.""" @@ -1084,7 +1082,7 @@ def Process(self, container: containers.Host) -> None: if not root_path: return self.logger.info( - 'Timeline to start from "{0:s}" items'.format(root_path.decode())) + f'Timeline to start from "{root_path.decode():s}" items') timeline_args = timeline_pb2.TimelineArgs(root=root_path,) flow_id = self._LaunchFlow(client, 'TimelineFlow', timeline_args) @@ -1112,7 +1110,7 @@ def _DownloadTimeline(self, client: Client, flow_id: str) -> Optional[str]: if os.path.exists(output_file_path): self.logger.info( - '{0:s} already exists: Skipping'.format(output_file_path)) + f'{output_file_path:s} already exists: Skipping') return None flow = client.Flow(flow_id) diff --git a/dftimewolf/lib/collectors/grr_hunt.py b/dftimewolf/lib/collectors/grr_hunt.py index 29b9fcf0..d89905c9 100644 --- a/dftimewolf/lib/collectors/grr_hunt.py +++ b/dftimewolf/lib/collectors/grr_hunt.py @@ -222,7 +222,7 @@ def Process(self) -> None: Raises: RuntimeError: if no items specified for collection. """ - self.logger.info('Artifacts to be collected: {0!s}'.format(self.artifacts)) + self.logger.info(f'Artifacts to be collected: {self.artifacts!s}') hunt_args = grr_flows.ArtifactCollectorFlowArgs( artifact_list=self.artifacts, use_raw_filesystem_access=self.use_raw_filesystem_access, @@ -316,9 +316,9 @@ def Process(self) -> None: RuntimeError: if no items specified for collection. """ self.logger.info( - 'Hunt to collect {0:d} items'.format(len(self.file_path_list))) + f'Hunt to collect {len(self.file_path_list):d} items') self.logger.info( - 'Files to be collected: {0!s}'.format(self.file_path_list)) + f'Files to be collected: {self.file_path_list!s}') hunt_action = grr_flows.FileFinderAction( action_type=grr_flows.FileFinderAction.DOWNLOAD, download=grr_flows.FileFinderDownloadActionOptions( @@ -544,7 +544,7 @@ def _CollectHuntResults(self, hunt: Hunt) -> List[Tuple[str, str]]: if os.path.exists(output_file_path): self.logger.info( - '{0:s} already exists: Skipping'.format(output_file_path)) + f'{output_file_path:s} already exists: Skipping') return [] self._WrapGRRRequestWithApproval( @@ -624,24 +624,22 @@ def _ExtractHuntResults(self, output_file_path: str) -> List[Tuple[str, str]]: try: archive.extract(f, self.output_path) except KeyError as exception: - self.logger.warning('Extraction error: {0:s}'.format(exception)) + self.logger.warning(f'Extraction error: {exception:s}') return [] except OSError as exception: - msg = 'Error manipulating file {0:s}: {1!s}'.format( - output_file_path, exception) + msg = f'Error manipulating file {output_file_path:s}: {exception!s}' self.ModuleError(msg, critical=True) except zipfile.BadZipfile as exception: - msg = 'Bad zipfile {0:s}: {1!s}'.format( - output_file_path, exception) + msg = f'Bad zipfile {output_file_path:s}: {exception!s}' self.ModuleError(msg, critical=True) try: os.remove(output_file_path) except OSError as exception: self.logger.warning( - 'Output path {0:s} could not be removed: {1:s}'.format( - output_file_path, exception)) + f'Output path {output_file_path:s} ' + f'could not be removed: {exception:s}') # Translate GRR client IDs to FQDNs with the information retrieved # earlier diff --git a/dftimewolf/lib/collectors/workspace_audit.py b/dftimewolf/lib/collectors/workspace_audit.py index 1bc0077e..bc14b9a6 100644 --- a/dftimewolf/lib/collectors/workspace_audit.py +++ b/dftimewolf/lib/collectors/workspace_audit.py @@ -78,7 +78,7 @@ def _GetCredentials(self) -> Credentials: credentials_path, self.SCOPES) except ValueError as exception: self.logger.warning( - 'Unable to load credentials: {0:s}'.format(exception)) + f'Unable to load credentials: {exception:s}') credentials = None # If there are no (valid) credentials available, let the user log in. @@ -146,7 +146,7 @@ def Process(self) -> None: output_file = tempfile.NamedTemporaryFile( mode='w', delete=False, encoding='utf-8', suffix='.jsonl') output_path = output_file.name - self.logger.info('Downloading logs to {0:s}'.format(output_path)) + self.logger.info(f'Downloading logs to {output_path:s}') audit_resource = self._BuildAuditResource(self._credentials) request_parameters = {