mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-10-08 22:46:41 +00:00
fix(backup): send host backup notifications over HTTPS when the Monitor uses it
This commit is contained in:
@@ -0,0 +1,58 @@
|
|||||||
|
"""A host backup and a finished restore tell the Monitor on its own port,
|
||||||
|
over HTTPS once the Monitor has a certificate."""
|
||||||
|
from pathlib import Path
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[3]
|
||||||
|
LIBRARY = ROOT / 'scripts/backup_restore/lib_host_backup_common.sh'
|
||||||
|
POSTBOOT = ROOT / 'scripts/backup_restore/apply_cluster_postboot.sh'
|
||||||
|
SETTING = '/etc/proxmenux/ssl_config.json'
|
||||||
|
|
||||||
|
|
||||||
|
def function(text, name):
|
||||||
|
start = text.index(name + '() {')
|
||||||
|
return text[start:text.index('\n}\n', start) + 3]
|
||||||
|
|
||||||
|
|
||||||
|
class BackupNotifyHttps(TestCase):
|
||||||
|
def address(self, setting):
|
||||||
|
with tempfile.TemporaryDirectory() as folder:
|
||||||
|
path = Path(folder) / 'ssl_config.json'
|
||||||
|
if setting is not None:
|
||||||
|
path.write_text(setting)
|
||||||
|
body = function(LIBRARY.read_text(), 'hb_notify_lifecycle').replace(SETTING, str(path))
|
||||||
|
# The function silences curl, so the stub writes the address it was given.
|
||||||
|
called = Path(folder) / 'called'
|
||||||
|
script = (f'curl() {{ printf "%s" "${{@: -1}}" > {called}; }}\n' + body
|
||||||
|
+ 'HB_NOTIFY_JOB_ID=job1 hb_notify_lifecycle complete\n')
|
||||||
|
result = subprocess.run(['/bin/bash', '--noprofile', '--norc', '-c', script],
|
||||||
|
capture_output=True, text=True, timeout=10)
|
||||||
|
self.assertEqual(result.returncode, 0, result.stderr)
|
||||||
|
return called.read_text()
|
||||||
|
|
||||||
|
def test_plain_http_while_the_monitor_has_no_certificate(self):
|
||||||
|
expected = 'http://127.0.0.1:8008/api/notifications/webhook'
|
||||||
|
self.assertEqual(self.address(None), expected)
|
||||||
|
self.assertEqual(self.address('{"enabled": false}'), expected)
|
||||||
|
|
||||||
|
def test_https_once_the_monitor_has_a_certificate(self):
|
||||||
|
self.assertEqual(self.address('{"enabled": true, "source": "proxmox"}'),
|
||||||
|
'https://127.0.0.1:8008/api/notifications/webhook')
|
||||||
|
|
||||||
|
def test_the_finished_restore_follows_the_same_setting(self):
|
||||||
|
source = POSTBOOT.read_text()
|
||||||
|
self.assertIn('"${NOTIFY_SCHEME}://127.0.0.1:8008/api/internal/restore-event"', source)
|
||||||
|
self.assertNotIn('"http://127.0.0.1:8008/api/internal/restore-event"', source)
|
||||||
|
check = source[source.index('NOTIFY_SCHEME="http"'):source.index('NOTIFY_HTTP=$(curl')]
|
||||||
|
with tempfile.TemporaryDirectory() as folder:
|
||||||
|
path = Path(folder) / 'ssl_config.json'
|
||||||
|
for setting, expected in (('{"enabled": true}', 'https'), ('{"enabled":false}', 'http'), (None, 'http')):
|
||||||
|
path.unlink(missing_ok=True)
|
||||||
|
if setting is not None:
|
||||||
|
path.write_text(setting)
|
||||||
|
result = subprocess.run(['/bin/bash', '--noprofile', '--norc', '-c',
|
||||||
|
check.replace(SETTING, str(path)) + '\necho "$NOTIFY_SCHEME"'],
|
||||||
|
capture_output=True, text=True, timeout=10)
|
||||||
|
self.assertEqual(result.stdout.strip(), expected, setting)
|
||||||
@@ -805,8 +805,12 @@ if command -v curl >/dev/null 2>&1; then
|
|||||||
"$POSTBOOT_DURATION_FMT" \
|
"$POSTBOOT_DURATION_FMT" \
|
||||||
"$SANITY_WARNINGS")
|
"$SANITY_WARNINGS")
|
||||||
fi
|
fi
|
||||||
NOTIFY_HTTP=$(curl -s -o /dev/null -w '%{http_code}' \
|
# The Monitor answers on the same port over HTTPS once it has a certificate.
|
||||||
-X POST "http://127.0.0.1:8008/api/internal/restore-event" \
|
NOTIFY_SCHEME="http"
|
||||||
|
grep -Eq '"enabled"[[:space:]]*:[[:space:]]*true' /etc/proxmenux/ssl_config.json 2>/dev/null && \
|
||||||
|
NOTIFY_SCHEME="https"
|
||||||
|
NOTIFY_HTTP=$(curl -sk -o /dev/null -w '%{http_code}' \
|
||||||
|
-X POST "${NOTIFY_SCHEME}://127.0.0.1:8008/api/internal/restore-event" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "$PAYLOAD" \
|
-d "$PAYLOAD" \
|
||||||
--max-time 5 2>/dev/null || echo "000")
|
--max-time 5 2>/dev/null || echo "000")
|
||||||
|
|||||||
@@ -3420,11 +3420,16 @@ Log: ${HB_NOTIFY_LOG_FILE:-}"
|
|||||||
log_file:$log, reason:$reason}}' \
|
log_file:$log, reason:$reason}}' \
|
||||||
2>/dev/null)
|
2>/dev/null)
|
||||||
[[ -z "$payload" ]] && return 0
|
[[ -z "$payload" ]] && return 0
|
||||||
|
# The Monitor answers on the same port over HTTPS once it has a certificate.
|
||||||
|
local scheme="http"
|
||||||
|
[[ -f /etc/proxmenux/ssl_config.json ]] && \
|
||||||
|
jq -e '.enabled' /etc/proxmenux/ssl_config.json >/dev/null 2>&1 && \
|
||||||
|
scheme="https"
|
||||||
curl -sk --connect-timeout 3 --max-time 5 \
|
curl -sk --connect-timeout 3 --max-time 5 \
|
||||||
-X POST \
|
-X POST \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "$payload" \
|
-d "$payload" \
|
||||||
http://127.0.0.1:8008/api/notifications/webhook \
|
"${scheme}://127.0.0.1:8008/api/notifications/webhook" \
|
||||||
>/dev/null 2>&1 || true
|
>/dev/null 2>&1 || true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user