Add SSH scan support with BSI TR-02102-4 compliance
- SSH scanning via ssh-audit (KEX, encryption, MAC, host keys) - BSI TR-02102-4 and IANA compliance validation for SSH - CSV/Markdown/reST reports for SSH results - Unified compliance schema and database views - Code optimization: modular query/writer architecture
This commit is contained in:
179
tests/compliance/test_targeted_compliance_issue.py
Normal file
179
tests/compliance/test_targeted_compliance_issue.py
Normal file
@@ -0,0 +1,179 @@
|
||||
"""Targeted test for specific compliance checking issues."""
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
|
||||
from sslysze_scan.db.compliance import check_compliance
|
||||
from sslysze_scan.db.writer import write_scan_results
|
||||
|
||||
|
||||
def test_specific_known_compliant_elements():
|
||||
"""Test that specifically known compliant elements are correctly identified as compliant.
|
||||
|
||||
This test verifies that specific, known compliant SSH and TLS elements
|
||||
are correctly matched against BSI/IANA compliance rules.
|
||||
"""
|
||||
# Use the template database for this test
|
||||
import shutil
|
||||
|
||||
template_db = (
|
||||
Path(__file__).parent.parent.parent
|
||||
/ "src"
|
||||
/ "sslysze_scan"
|
||||
/ "data"
|
||||
/ "crypto_standards.db"
|
||||
)
|
||||
with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as temp_db:
|
||||
db_path = temp_db.name
|
||||
# Copy the template database to use as our test database
|
||||
shutil.copy2(template_db, db_path)
|
||||
|
||||
try:
|
||||
# Create scan results with specifically known compliant elements that exist in the databases
|
||||
scan_results = {
|
||||
22: {
|
||||
# These are known to be compliant with BSI standards (from bsi_tr_02102_4_ssh_kex table)
|
||||
"kex_algorithms": ["ecdh-sha2-nistp256", "diffie-hellman-group16-sha512"],
|
||||
"encryption_algorithms_client_to_server": [
|
||||
"chacha20-poly1305@openssh.com", # From IANA list
|
||||
"aes256-ctr", # From IANA list
|
||||
],
|
||||
"encryption_algorithms_server_to_client": [
|
||||
"chacha20-poly1305@openssh.com",
|
||||
"aes256-ctr",
|
||||
],
|
||||
"mac_algorithms_client_to_server": [
|
||||
"hmac-sha2-256",
|
||||
"hmac-sha2-512",
|
||||
], # From IANA list
|
||||
"mac_algorithms_server_to_client": ["hmac-sha2-256", "hmac-sha2-512"],
|
||||
"host_keys": [
|
||||
{
|
||||
"algorithm": "rsa-sha2-512", # From BSI list
|
||||
"type": "rsa",
|
||||
"bits": 4096,
|
||||
"fingerprint": "aa:bb:cc:dd:ee:ff:gg:hh:ii:jj:kk:ll:mm:nn:oo:pp",
|
||||
},
|
||||
{
|
||||
"algorithm": "ecdsa-sha2-nistp256", # From BSI list
|
||||
"type": "ecdsa",
|
||||
"bits": 256,
|
||||
"fingerprint": "qq:rr:ss:tt:uu:vv:ww:xx:yy:zz:aa:bb:cc:dd:ee:ff",
|
||||
},
|
||||
],
|
||||
},
|
||||
443: {
|
||||
"tls_versions": ["TLS_1_2", "TLS_1_3"],
|
||||
"cipher_suites": {
|
||||
"TLS_1_3": [
|
||||
"TLS_AES_256_GCM_SHA384",
|
||||
"TLS_CHACHA20_POLY1305_SHA256",
|
||||
], # From IANA list
|
||||
"TLS_1_2": [
|
||||
"ECDHE-RSA-AES256-GCM-SHA384", # From IANA list
|
||||
"ECDHE-RSA-AES128-GCM-SHA256",
|
||||
],
|
||||
},
|
||||
"supported_groups": [
|
||||
"X25519",
|
||||
"secp256r1",
|
||||
"secp384r1",
|
||||
], # From IANA list
|
||||
"certificates": [
|
||||
{
|
||||
"subject": "CN=test.example.com",
|
||||
"issuer": "CN=Test CA",
|
||||
"key_type": "RSA",
|
||||
"key_bits": 4096,
|
||||
"signature_algorithm": "sha256WithRSAEncryption",
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
# Save scan results to database using the regular save function
|
||||
scan_start_time = datetime.now(UTC)
|
||||
scan_id = write_scan_results(
|
||||
db_path,
|
||||
"test.example.com",
|
||||
[22, 443],
|
||||
scan_results,
|
||||
scan_start_time,
|
||||
1.0, # duration
|
||||
)
|
||||
|
||||
assert scan_id is not None
|
||||
assert scan_id > 0
|
||||
|
||||
# Check compliance
|
||||
compliance_results = check_compliance(db_path, scan_id)
|
||||
|
||||
# The test should fail if known compliant elements are not recognized as compliant
|
||||
# This will highlight the specific issue with the compliance checking logic
|
||||
|
||||
print(
|
||||
f"SSH KEX checked: {compliance_results['ssh_kex_checked']}, passed: {compliance_results['ssh_kex_passed']}"
|
||||
)
|
||||
print(
|
||||
f"SSH Encryption checked: {compliance_results['ssh_encryption_checked']}, passed: {compliance_results['ssh_encryption_passed']}"
|
||||
)
|
||||
print(
|
||||
f"SSH MAC checked: {compliance_results['ssh_mac_checked']}, passed: {compliance_results['ssh_mac_passed']}"
|
||||
)
|
||||
print(
|
||||
f"SSH Host Keys checked: {compliance_results['ssh_host_keys_checked']}, passed: {compliance_results['ssh_host_keys_passed']}"
|
||||
)
|
||||
print(
|
||||
f"Cipher suites checked: {compliance_results['cipher_suites_checked']}, passed: {compliance_results['cipher_suites_passed']}"
|
||||
)
|
||||
print(
|
||||
f"Supported groups checked: {compliance_results['supported_groups_checked']}, passed: {compliance_results['supported_groups_passed']}"
|
||||
)
|
||||
|
||||
# These assertions will fail if the compliance checking logic is not working correctly
|
||||
# This is the targeted test for the specific issue
|
||||
assert (
|
||||
compliance_results["ssh_kex_checked"] == 0
|
||||
or compliance_results["ssh_kex_passed"] > 0
|
||||
), (
|
||||
f"Known compliant SSH KEX methods should be recognized as compliant, but got {compliance_results['ssh_kex_passed']}/{compliance_results['ssh_kex_checked']} passed"
|
||||
)
|
||||
|
||||
assert (
|
||||
compliance_results["ssh_encryption_checked"] == 0
|
||||
or compliance_results["ssh_encryption_passed"] > 0
|
||||
), (
|
||||
f"Known compliant SSH encryption algorithms should be recognized as compliant, but got {compliance_results['ssh_encryption_passed']}/{compliance_results['ssh_encryption_checked']} passed"
|
||||
)
|
||||
|
||||
assert (
|
||||
compliance_results["ssh_mac_checked"] == 0
|
||||
or compliance_results["ssh_mac_passed"] > 0
|
||||
), (
|
||||
f"Known compliant SSH MAC algorithms should be recognized as compliant, but got {compliance_results['ssh_mac_passed']}/{compliance_results['ssh_mac_checked']} passed"
|
||||
)
|
||||
|
||||
assert (
|
||||
compliance_results["ssh_host_keys_checked"] == 0
|
||||
or compliance_results["ssh_host_keys_passed"] > 0
|
||||
), (
|
||||
f"Known compliant SSH host keys should be recognized as compliant, but got {compliance_results['ssh_host_keys_passed']}/{compliance_results['ssh_host_keys_checked']} passed"
|
||||
)
|
||||
|
||||
# For TLS elements, if they were checked, they should have some compliant ones
|
||||
if compliance_results["cipher_suites_checked"] > 0:
|
||||
assert compliance_results["cipher_suites_passed"] > 0, (
|
||||
f"Known compliant cipher suites should be recognized as compliant, but got {compliance_results['cipher_suites_passed']}/{compliance_results['cipher_suites_checked']} passed"
|
||||
)
|
||||
|
||||
if compliance_results["supported_groups_checked"] > 0:
|
||||
assert compliance_results["supported_groups_passed"] > 0, (
|
||||
f"Known compliant supported groups should be recognized as compliant, but got {compliance_results['supported_groups_passed']}/{compliance_results['supported_groups_checked']} passed"
|
||||
)
|
||||
|
||||
finally:
|
||||
# Clean up temporary database
|
||||
if os.path.exists(db_path):
|
||||
os.unlink(db_path)
|
||||
Reference in New Issue
Block a user