Skip to content

Commit cfc760d

Browse files
authored
Merge pull request #314 from xcp-ng/Add_security_test
Add TLS_Test & XOA deployment
2 parents 5ab3f03 + 1bb032c commit cfc760d

File tree

3 files changed

+103
-0
lines changed

3 files changed

+103
-0
lines changed

jobs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
},
2424
"paths": [
2525
"tests/misc",
26+
"tests/security",
2627
"tests/migration",
2728
"tests/network",
2829
"tests/snapshot",

tests/misc/test_access_links.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import pytest
2+
import subprocess
3+
import hashlib
4+
5+
# This test is designed to verify the accessibility of the XOA deployment script
6+
#
7+
# Requirements:
8+
# - an XCP-ng host with xcp-ng-release >= 8.3.0.29
9+
10+
@pytest.mark.parametrize("command_id", ["curl", "wget"])
11+
@pytest.mark.parametrize("url_id", [
12+
"xoa",
13+
"xcp-ng",
14+
"vates"
15+
])
16+
def test_access_links(host, command_id, url_id):
17+
"""
18+
Verifies that the specified URL responds correctly via the specified command
19+
and compares the checksum of the downloaded content between local and remote.
20+
"""
21+
command = {"curl": "curl -fsSL",
22+
"wget": "wget -qO-"}[command_id]
23+
url = {
24+
"xoa": "https://xoa.io/deploy",
25+
"xcpng": "https://updates.xcp-ng.org/trace",
26+
"vates": "https://repo.vates.tech/README.txt"
27+
}[url_id]
28+
COMMAND = f"{command} '{url}'"
29+
30+
# Download from remote host
31+
remote_result = host.ssh(COMMAND)
32+
33+
# Verify the download worked by comparing with local download
34+
# This ensures the content is accessible and identical from both locations
35+
local_result = host.local_cmd(COMMAND)
36+
37+
assert local_result.returncode == 0, (
38+
f"Failed to fetch URL locally: {local_result.stderr}"
39+
)
40+
41+
# Extract checksums
42+
local_checksum = hashlib.sha256(local_result.stdout.split()[0].encode('utf-8')).hexdigest()
43+
remote_checksum = hashlib.sha256(remote_result.split()[0].encode('utf-8')).hexdigest()
44+
45+
assert local_checksum == remote_checksum, (
46+
f"Checksum mismatch: local ({local_checksum}) != remote ({remote_checksum})"
47+
)

tests/security/test_tls.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import pytest
2+
import ssl
3+
import socket
4+
import logging
5+
6+
# This test is designed to verify that TLS connections is secured
7+
#
8+
# Requirements:
9+
# - An XCP-ng host
10+
11+
@pytest.mark.parametrize("protocol_name", ["TLSv1", "TLSv1.1"])
12+
def test_tls_disabled(host: str, protocol_name: str):
13+
"""
14+
Verifies that specified TLS protocols are disabled on the XCP-ng host.
15+
Uses the ssl library directly. Should raise SSLError.
16+
"""
17+
PORT = 443
18+
19+
protocol = {
20+
"TLSv1": ssl.PROTOCOL_TLSv1,
21+
"TLSv1.1": ssl.PROTOCOL_TLSv1_1
22+
}[protocol_name]
23+
24+
logging.info(f"Testing if protocol {protocol_name} is disabled on host {host}")
25+
26+
with pytest.raises(ssl.SSLError):
27+
context = ssl.SSLContext(protocol)
28+
with socket.create_connection((str(host), PORT), timeout=10) as sock:
29+
with context.wrap_socket(sock, server_hostname=str(host)) as ssock:
30+
ssock.do_handshake()
31+
# If we reach this point, the protocol is enabled (test should fail)
32+
pytest.fail(f"Protocol {protocol} should be disabled but connection succeeded")
33+
34+
@pytest.mark.parametrize("protocol_name", ["TLSv1.2"])
35+
def test_enabled(host: str, protocol_name: str):
36+
"""
37+
Verifies that TLSv1.2 is enabled on the XCP-ng host.
38+
Uses the ssl library directly.
39+
"""
40+
PORT = 443
41+
42+
protocol = {
43+
"TLSv1.2": ssl.PROTOCOL_TLSv1_2
44+
}[protocol_name]
45+
46+
logging.info(f"Testing if protocol {protocol_name} is enabled on host {host}")
47+
48+
try:
49+
context = ssl.SSLContext(protocol)
50+
with socket.create_connection((str(host), PORT), timeout=10) as sock:
51+
with context.wrap_socket(sock, server_hostname=str(host)) as ssock:
52+
ssock.do_handshake()
53+
assert ssock.version()
54+
except ssl.SSLError as e:
55+
pytest.fail(f"{protocol_name} should be enabled, but got SSLError: {e}")

0 commit comments

Comments
 (0)