diff --git a/borgmatic/config/schema.yaml b/borgmatic/config/schema.yaml index 1e238721..8325e26e 100644 --- a/borgmatic/config/schema.yaml +++ b/borgmatic/config/schema.yaml @@ -2200,6 +2200,12 @@ properties: - start - finish - fail + verify_tls: + type: boolean + description: | + Verify the TLS certificate of the push URL host. Defaults to + true. + example: false description: | Configuration for a monitoring integration with Uptime Kuma using the Push monitor type. diff --git a/borgmatic/hooks/monitoring/uptime_kuma.py b/borgmatic/hooks/monitoring/uptime_kuma.py index 015dde0b..68d5f29b 100644 --- a/borgmatic/hooks/monitoring/uptime_kuma.py +++ b/borgmatic/hooks/monitoring/uptime_kuma.py @@ -37,7 +37,7 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev logging.getLogger('urllib3').setLevel(logging.ERROR) try: - response = requests.get(f'{push_url}?{query}') + response = requests.get(f'{push_url}?{query}', verify=hook_config.get('verify_tls', True)) if not response.ok: response.raise_for_status() except requests.exceptions.RequestException as error: diff --git a/tests/unit/hooks/monitoring/test_uptimekuma.py b/tests/unit/hooks/monitoring/test_uptimekuma.py index b29e1c44..a9d00bee 100644 --- a/tests/unit/hooks/monitoring/test_uptimekuma.py +++ b/tests/unit/hooks/monitoring/test_uptimekuma.py @@ -10,7 +10,7 @@ CUSTOM_PUSH_URL = 'https://uptime.example.com/api/push/efgh5678' def test_ping_monitor_hits_default_uptimekuma_on_fail(): hook_config = {} flexmock(module.requests).should_receive('get').with_args( - f'{DEFAULT_PUSH_URL}?status=down&msg=fail' + f'{DEFAULT_PUSH_URL}?status=down&msg=fail', verify=True ).and_return(flexmock(ok=True)).once() module.ping_monitor( @@ -26,7 +26,7 @@ def test_ping_monitor_hits_default_uptimekuma_on_fail(): def test_ping_monitor_hits_custom_uptimekuma_on_fail(): hook_config = {'push_url': CUSTOM_PUSH_URL} flexmock(module.requests).should_receive('get').with_args( - f'{CUSTOM_PUSH_URL}?status=down&msg=fail' + f'{CUSTOM_PUSH_URL}?status=down&msg=fail', verify=True ).and_return(flexmock(ok=True)).once() module.ping_monitor( @@ -42,7 +42,7 @@ def test_ping_monitor_hits_custom_uptimekuma_on_fail(): def test_ping_monitor_custom_uptimekuma_on_start(): hook_config = {'push_url': CUSTOM_PUSH_URL} flexmock(module.requests).should_receive('get').with_args( - f'{CUSTOM_PUSH_URL}?status=up&msg=start' + f'{CUSTOM_PUSH_URL}?status=up&msg=start', verify=True ).and_return(flexmock(ok=True)).once() module.ping_monitor( @@ -58,7 +58,7 @@ def test_ping_monitor_custom_uptimekuma_on_start(): def test_ping_monitor_custom_uptimekuma_on_finish(): hook_config = {'push_url': CUSTOM_PUSH_URL} flexmock(module.requests).should_receive('get').with_args( - f'{CUSTOM_PUSH_URL}?status=up&msg=finish' + f'{CUSTOM_PUSH_URL}?status=up&msg=finish', verify=True ).and_return(flexmock(ok=True)).once() module.ping_monitor( @@ -116,7 +116,7 @@ def test_ping_monitor_does_not_hit_custom_uptimekuma_on_finish_dry_run(): def test_ping_monitor_with_connection_error_logs_warning(): hook_config = {'push_url': CUSTOM_PUSH_URL} flexmock(module.requests).should_receive('get').with_args( - f'{CUSTOM_PUSH_URL}?status=down&msg=fail' + f'{CUSTOM_PUSH_URL}?status=down&msg=fail', verify=True ).and_raise(module.requests.exceptions.ConnectionError) flexmock(module.logger).should_receive('warning').once() @@ -137,7 +137,7 @@ def test_ping_monitor_with_other_error_logs_warning(): module.requests.exceptions.RequestException ) flexmock(module.requests).should_receive('get').with_args( - f'{CUSTOM_PUSH_URL}?status=down&msg=fail' + f'{CUSTOM_PUSH_URL}?status=down&msg=fail', verify=True ).and_return(response) flexmock(module.logger).should_receive('warning').once() @@ -163,3 +163,35 @@ def test_ping_monitor_with_invalid_run_state(): monitoring_log_level=1, dry_run=True, ) + + +def test_ping_monitor_skips_ssl_verification_when_verify_tls_false(): + hook_config = {'push_url': CUSTOM_PUSH_URL, 'verify_tls': False} + flexmock(module.requests).should_receive('get').with_args( + f'{CUSTOM_PUSH_URL}?status=down&msg=fail', verify=False + ).and_return(flexmock(ok=True)).once() + + module.ping_monitor( + hook_config, + {}, + 'config.yaml', + borgmatic.hooks.monitoring.monitor.State.FAIL, + monitoring_log_level=1, + dry_run=False, + ) + + +def test_ping_monitor_executes_ssl_verification_when_verify_tls_true(): + hook_config = {'push_url': CUSTOM_PUSH_URL, 'verify_tls': True} + flexmock(module.requests).should_receive('get').with_args( + f'{CUSTOM_PUSH_URL}?status=down&msg=fail', verify=True + ).and_return(flexmock(ok=True)).once() + + module.ping_monitor( + hook_config, + {}, + 'config.yaml', + borgmatic.hooks.monitoring.monitor.State.FAIL, + monitoring_log_level=1, + dry_run=False, + )