Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UX: history command #435

Merged
merged 14 commits into from
Jun 5, 2024
23 changes: 19 additions & 4 deletions pacu/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import os
import random
import re
import readline
import shlex
import subprocess
import sys
Expand Down Expand Up @@ -42,6 +43,11 @@
print('Refer to https://github.com/RhinoSecurityLabs/pacu/wiki/Installation')
sys.exit(1)

# arbitrary number, seems reasonable though
readline.set_history_length(200)
if os.path.isfile(settings.history_file) and os.access(settings.history_file, os.R_OK):
readline.read_history_file(settings.history_file)


def load_categories() -> set:
categories = set()
Expand Down Expand Up @@ -126,6 +132,7 @@ def display_pacu_help():
swap_session <session name> Change the active Pacu session to another one in the database
delete_session Delete a Pacu session from the database. Note that the output
folder for that session will not be deleted
history List the previously typed commands

exit/quit Exit Pacu

Expand Down Expand Up @@ -177,9 +184,9 @@ def get_data_from_traceback(tb) -> Tuple[Optional[PacuSession], List[str], List[
class Main:
COMMANDS = [
'assume_role', 'aws', 'console', 'data', 'delete_session', 'exec', 'exit', 'export_keys', 'help',
'import_keys', 'list', 'list_sessions', 'load_commands_file', 'ls', 'open_console', 'quit', 'regions',
'run', 'search', 'services', 'sessions', 'set_keys', 'set_regions', 'set_ua_suffix', 'swap_keys',
'swap_session', 'unset_ua_suffix', 'update_regions', 'use', 'whoami'
'history', 'import_keys', 'list', 'list_sessions', 'load_commands_file', 'ls', 'open_console', 'quit',
'regions', 'run', 'search', 'services', 'sessions', 'set_keys', 'set_regions', 'set_ua_suffix',
'swap_keys', 'swap_session', 'unset_ua_suffix', 'update_regions', 'use', 'whoami'
]

def __init__(self):
Expand Down Expand Up @@ -366,6 +373,11 @@ def get_regions(self, service, check_session=True) -> List[Optional[str]]:
else:
return valid_regions

def display_history(self):
# https://stackoverflow.com/a/7008316
for i in range(readline.get_current_history_length()):
print("{:>3}: {}".format(i+1, readline.get_history_item(i + 1)))

def display_all_regions(self):
for region in sorted(self.get_regions('all')):
print(' {}'.format(region))
Expand Down Expand Up @@ -595,6 +607,8 @@ def parse_command(self, command):
self.parse_commands_from_file(command)
elif command[0] == 'regions':
self.display_all_regions()
elif command[0] == 'history':
self.display_history()
elif command[0] in ['run', 'exec', 'use']:
self.print_user_agent_suffix()
self.parse_exec_module_command(command)
Expand All @@ -620,6 +634,8 @@ def parse_command(self, command):
elif command[0] == 'whoami':
self.print_key_info()
elif command[0] == 'exit' or command[0] == 'quit':
# write out command history for loading later
readline.write_history_file(settings.history_file)
self.exit()
else:
print(' Error: Unrecognized command')
Expand Down Expand Up @@ -1579,7 +1595,6 @@ def get_boto3_resource(

def initialize_tab_completion(self) -> None:
try:
import readline
# Big thanks to samplebias: https://stackoverflow.com/a/5638688
MODULES = []
CATEGORIES = []
Expand Down
2 changes: 2 additions & 0 deletions pacu/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
_home_dir = Path('~/.local/share/pacu')
home_dir = _home_dir.expanduser().absolute()

history_file = f'{home_dir}/command_history.txt'

os.makedirs(home_dir, exist_ok=True, mode=0o700)

DATABASE_FILE_PATH = os.path.join(home_dir, 'sqlite.db')
Expand Down
Loading