Mask the password when logging a MongoDB dump or restore command (#848).
This commit is contained in:
parent
f9182514d8
commit
7e51c41ebf
3 changed files with 40 additions and 1 deletions
1
NEWS
1
NEWS
|
@ -9,6 +9,7 @@
|
||||||
* #843: Add documentation link to Loki dashboard for borgmatic:
|
* #843: Add documentation link to Loki dashboard for borgmatic:
|
||||||
https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/#loki-hook
|
https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/#loki-hook
|
||||||
* #847: Fix "--json" error when Borg includes non-JSON warnings in JSON output.
|
* #847: Fix "--json" error when Borg includes non-JSON warnings in JSON output.
|
||||||
|
* #848: SECURITY: Mask the password when logging a MongoDB dump or restore command.
|
||||||
* Fix handling of the NO_COLOR environment variable to ignore an empty value.
|
* Fix handling of the NO_COLOR environment variable to ignore an empty value.
|
||||||
* Add documentation about backing up containerized databases by configuring borgmatic to exec into
|
* Add documentation about backing up containerized databases by configuring borgmatic to exec into
|
||||||
a container to run a dump command:
|
a container to run a dump command:
|
||||||
|
|
|
@ -220,6 +220,24 @@ def log_outputs(processes, exclude_stdouts, output_log_level, borg_local_path, b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SECRET_COMMAND_FLAG_NAMES = {'--password'}
|
||||||
|
|
||||||
|
|
||||||
|
def mask_command_secrets(full_command):
|
||||||
|
'''
|
||||||
|
Given a command as a sequence, mask secret values for flags like "--password" in preparation for
|
||||||
|
logging.
|
||||||
|
'''
|
||||||
|
masked_command = []
|
||||||
|
previous_piece = None
|
||||||
|
|
||||||
|
for piece in full_command:
|
||||||
|
masked_command.append('***' if previous_piece in SECRET_COMMAND_FLAG_NAMES else piece)
|
||||||
|
previous_piece = piece
|
||||||
|
|
||||||
|
return tuple(masked_command)
|
||||||
|
|
||||||
|
|
||||||
MAX_LOGGED_COMMAND_LENGTH = 1000
|
MAX_LOGGED_COMMAND_LENGTH = 1000
|
||||||
|
|
||||||
|
|
||||||
|
@ -231,7 +249,8 @@ def log_command(full_command, input_file=None, output_file=None, environment=Non
|
||||||
logger.debug(
|
logger.debug(
|
||||||
textwrap.shorten(
|
textwrap.shorten(
|
||||||
' '.join(
|
' '.join(
|
||||||
tuple(f'{key}=***' for key in (environment or {}).keys()) + tuple(full_command)
|
tuple(f'{key}=***' for key in (environment or {}).keys())
|
||||||
|
+ mask_command_secrets(full_command)
|
||||||
),
|
),
|
||||||
width=MAX_LOGGED_COMMAND_LENGTH,
|
width=MAX_LOGGED_COMMAND_LENGTH,
|
||||||
placeholder=' ...',
|
placeholder=' ...',
|
||||||
|
|
|
@ -117,6 +117,24 @@ def test_append_last_lines_with_output_log_level_none_appends_captured_output():
|
||||||
assert captured_output == ['captured', 'line']
|
assert captured_output == ['captured', 'line']
|
||||||
|
|
||||||
|
|
||||||
|
def test_mask_command_secrets_masks_password_flag_value():
|
||||||
|
assert module.mask_command_secrets(('cooldb', '--username', 'bob', '--password', 'pass')) == (
|
||||||
|
'cooldb',
|
||||||
|
'--username',
|
||||||
|
'bob',
|
||||||
|
'--password',
|
||||||
|
'***',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_mask_command_secrets_passes_through_other_commands():
|
||||||
|
assert module.mask_command_secrets(('cooldb', '--username', 'bob')) == (
|
||||||
|
'cooldb',
|
||||||
|
'--username',
|
||||||
|
'bob',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'full_command,input_file,output_file,environment,expected_result',
|
'full_command,input_file,output_file,environment,expected_result',
|
||||||
(
|
(
|
||||||
|
@ -149,6 +167,7 @@ def test_append_last_lines_with_output_log_level_none_appends_captured_output():
|
||||||
def test_log_command_logs_command_constructed_from_arguments(
|
def test_log_command_logs_command_constructed_from_arguments(
|
||||||
full_command, input_file, output_file, environment, expected_result
|
full_command, input_file, output_file, environment, expected_result
|
||||||
):
|
):
|
||||||
|
flexmock(module).should_receive('mask_command_secrets').replace_with(lambda command: command)
|
||||||
flexmock(module.logger).should_receive('debug').with_args(expected_result).once()
|
flexmock(module.logger).should_receive('debug').with_args(expected_result).once()
|
||||||
|
|
||||||
module.log_command(full_command, input_file, output_file, environment)
|
module.log_command(full_command, input_file, output_file, environment)
|
||||||
|
|
Loading…
Reference in a new issue