Skip to content

Commit

Permalink
Merge branch 'RhinoSecurityLabs:master' into improve-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
EduardSchwarzkopf authored Jun 8, 2024
2 parents 440b0e1 + b32a306 commit acbd443
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 10 deletions.
48 changes: 38 additions & 10 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 @@ -108,7 +114,7 @@ def display_pacu_help():
appended to the user agent for all API calls. If no suffix is
supplied a UUID-based suffix will be generated.
unset_ua_suffix Remove the user agent suffix for this session.
run/exec <module name> Execute a module
run/exec/use <module name> Execute a module
set_keys Add a set of AWS keys to the session and set them as the
default
swap_keys Change the currently active AWS key to another key that has
Expand All @@ -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 All @@ -143,6 +150,7 @@ def display_pacu_help():
to solve this problem
console/open_console Generate a URL that will log the current user/role in to
the AWS web console
debug Display the contents of the error log file
""")


Expand Down Expand Up @@ -176,10 +184,10 @@ def get_data_from_traceback(tb) -> Tuple[Optional[PacuSession], List[str], List[

class Main:
COMMANDS = [
'aws', 'data', 'exec', 'exit', 'help', 'import_keys', 'assume_role', 'list', 'load_commands_file',
'ls', 'quit', 'regions', 'run', 'search', 'services', 'set_keys', 'set_regions',
'swap_keys', 'update_regions', 'set_ua_suffix', 'unset_ua_suffix', 'whoami', 'swap_session', 'sessions',
'list_sessions', 'delete_session', 'export_keys', 'open_console', 'console'
'assume_role', 'aws', 'console', 'data', 'delete_session', 'exec', 'exit', 'export_keys', 'help',
'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', 'debug'
]

def __init__(self):
Expand Down Expand Up @@ -211,8 +219,8 @@ def log_error(self, text, exception_info=None, session=None, local_data=None, gl
log_file_path = '{}/global_error_log.txt'.format(session_dir())

print('\n[{}] Pacu encountered an error while running the previous command. Check {} for technical '
'details. [LOG LEVEL: {}]\n\n {}\n'.format(timestamp, log_file_path,
settings.ERROR_LOG_VERBOSITY.upper(), exception_info))
'details, or use the debug command. [LOG LEVEL: {}]\n\n {}\n'.format(timestamp, log_file_path,
settings.ERROR_LOG_VERBOSITY.upper(), exception_info))

log_file_directory = os.path.dirname(log_file_path)
if log_file_directory and not os.path.exists(log_file_directory):
Expand Down Expand Up @@ -256,6 +264,14 @@ def log_error(self, text, exception_info=None, session=None, local_data=None, gl
'and should most likely be provided to the developers.\n Exception raised: {}'.format(str(error)))
raise

def read_log_file(self):
log_file_path = '{}/error_log.txt'.format(session_dir())
if os.path.exists(log_file_path):
with open(log_file_path, 'r') as log_file:
print(log_file.read())
else:
print('No error log file found.')

# @message: String - message to print and/or write to file
# @output: String - where to output the message: both, file, or screen
# @output_type: String - format for message when written to file: plain or xml
Expand Down Expand Up @@ -366,6 +382,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,7 +616,9 @@ def parse_command(self, command):
self.parse_commands_from_file(command)
elif command[0] == 'regions':
self.display_all_regions()
elif command[0] == 'run' or command[0] == 'exec':
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)
elif command[0] == 'search':
Expand All @@ -619,7 +642,11 @@ def parse_command(self, command):
self.unset_user_agent_suffix()
elif command[0] == 'whoami':
self.print_key_info()
elif command[0] == 'debug':
self.read_log_file()
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 @@ -782,7 +809,9 @@ def parse_list_command(self, command):
self.list_modules(command[2], by_category=True)

def parse_exec_module_command(self, command: List[str]) -> None:
if len(command) > 1:
if len(command) > 1 and command[-1] == "-h":
self.parse_help_command(command)
elif len(command) > 1:
self.exec_module(command)
else:
print('The {} command requires a module name. Try using the module search function.'.format(command))
Expand Down Expand Up @@ -1577,7 +1606,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
1 change: 1 addition & 0 deletions pacu/modules/iam__enum_permissions/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,7 @@ def summary(data, pacu_main):
out += "{:>{count_max_len}} Unconfirmed permissions for {} role(s).\n".format(data["roles_unconfirmed_perm_count"],
data["roles_unconfirmed"],
count_max_len=count_max_len)
out += "Type 'whoami' to see detailed list of permissions.\n"
return out


Expand Down
2 changes: 2 additions & 0 deletions pacu/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,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

0 comments on commit acbd443

Please sign in to comment.