aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/conftest.py1
-rw-r--r--tests/data/mtr_fatbeam.json206
-rw-r--r--tests/data/nmaprun1.xml68
-rw-r--r--tests/data/nmaprun2.xml118
-rw-r--r--tests/managers/network/__init__.py0
-rw-r--r--tests/managers/network/test_label.py202
-rw-r--r--tests/managers/network/test_tool_run.py25
-rw-r--r--tests/models/network/__init__.py0
-rw-r--r--tests/models/network/test_mtr.py26
-rw-r--r--tests/models/network/test_nmap.py29
-rw-r--r--tests/models/network/test_nmap_parser.py22
-rw-r--r--tests/models/network/test_rdns.py33
12 files changed, 730 insertions, 0 deletions
diff --git a/tests/conftest.py b/tests/conftest.py
index 30ed1c7..2482269 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -13,6 +13,7 @@ pytest_plugins = [
"test_utils.managers.conftest",
"test_utils.managers.contest.conftest",
"test_utils.managers.ledger.conftest",
+ "test_utils.managers.network.conftest",
"test_utils.managers.upk.conftest",
# -- Models
"test_utils.models.conftest",
diff --git a/tests/data/mtr_fatbeam.json b/tests/data/mtr_fatbeam.json
new file mode 100644
index 0000000..6e27eb1
--- /dev/null
+++ b/tests/data/mtr_fatbeam.json
@@ -0,0 +1,206 @@
+{
+ "report": {
+ "mtr": {
+ "src": "gstupp-ThinkPad-X1-Carbon-Gen-11",
+ "dst": "167.150.6.80",
+ "tos": 0,
+ "tests": 10,
+ "psize": "64",
+ "bitpattern": "0x00"
+ },
+ "hubs": [
+ {
+ "count": 1,
+ "host": "_gateway (172.20.20.1)",
+ "ASN": "AS???",
+ "Loss%": 0.0,
+ "Snt": 10,
+ "Last": 2.408,
+ "Avg": 16.157,
+ "Best": 2.408,
+ "Wrst": 69.531,
+ "StDev": 20.69
+ },
+ {
+ "count": 2,
+ "host": "172.16.20.1",
+ "ASN": "AS???",
+ "Loss%": 0.0,
+ "Snt": 10,
+ "Last": 3.411,
+ "Avg": 16.906,
+ "Best": 2.613,
+ "Wrst": 90.7,
+ "StDev": 27.547
+ },
+ {
+ "count": 3,
+ "host": "192.168.1.254",
+ "ASN": "AS???",
+ "Loss%": 0.0,
+ "Snt": 10,
+ "Last": 17.012,
+ "Avg": 9.812,
+ "Best": 3.061,
+ "Wrst": 25.728,
+ "StDev": 8.908
+ },
+ {
+ "count": 4,
+ "host": "ipdsl-jal-ptovallarta-19-l0.uninet.net.mx (201.154.95.117)",
+ "ASN": "AS???",
+ "Loss%": 0.0,
+ "Snt": 10,
+ "Last": 6.954,
+ "Avg": 10.216,
+ "Best": 6.177,
+ "Wrst": 16.151,
+ "StDev": 3.343
+ },
+ {
+ "count": 5,
+ "host": "bb-la-onewilshire-29-ae32_0.uninet.net.mx (189.246.202.49)",
+ "ASN": "AS???",
+ "Loss%": 0.0,
+ "Snt": 10,
+ "Last": 52.557,
+ "Avg": 54.174,
+ "Best": 45.681,
+ "Wrst": 71.387,
+ "StDev": 8.011
+ },
+ {
+ "count": 6,
+ "host": "ae91.edge7.LosAngeles1.Level3.net (4.7.28.197)",
+ "ASN": "AS3356",
+ "Loss%": 0.0,
+ "Snt": 10,
+ "Last": 1079.2,
+ "Avg": 875.97,
+ "Best": 47.78,
+ "Wrst": 4150.5,
+ "StDev": 1345.7
+ },
+ {
+ "count": 7,
+ "host": "???",
+ "ASN": "AS???",
+ "Loss%": 100.0,
+ "Snt": 10,
+ "Last": 0.0,
+ "Avg": 0.0,
+ "Best": 0.0,
+ "Wrst": 0.0,
+ "StDev": 0.0
+ },
+ {
+ "count": 8,
+ "host": "ae10.cr1.lax10.us.zip.zayo.com (64.125.28.224)",
+ "ASN": "AS6461",
+ "Loss%": 70.0,
+ "Snt": 10,
+ "Last": 1186.5,
+ "Avg": 2189.8,
+ "Best": 1186.5,
+ "Wrst": 3202.8,
+ "StDev": 1008.2
+ },
+ {
+ "count": 9,
+ "host": "ae16.cr1.sjc1.us.zip.zayo.com (64.125.21.171)",
+ "ASN": "AS6461",
+ "Loss%": 0.0,
+ "Snt": 10,
+ "Last": 92.819,
+ "Avg": 414.75,
+ "Best": 90.799,
+ "Wrst": 2140.8,
+ "StDev": 690.96
+ },
+ {
+ "count": 10,
+ "host": "ae27.cs3.sjc7.us.zip.zayo.com (64.125.18.28)",
+ "ASN": "AS6461",
+ "Loss%": 90.0,
+ "Snt": 10,
+ "Last": 5234.8,
+ "Avg": 5234.8,
+ "Best": 5234.8,
+ "Wrst": 5234.8,
+ "StDev": 0.0
+ },
+ {
+ "count": 11,
+ "host": "???",
+ "ASN": "AS???",
+ "Loss%": 100.0,
+ "Snt": 10,
+ "Last": 0.0,
+ "Avg": 0.0,
+ "Best": 0.0,
+ "Wrst": 0.0,
+ "StDev": 0.0
+ },
+ {
+ "count": 12,
+ "host": "ae8.cr1.sea1.us.zip.zayo.com (64.125.28.193)",
+ "ASN": "AS6461",
+ "Loss%": 0.0,
+ "Snt": 10,
+ "Last": 93.389,
+ "Avg": 1238.6,
+ "Best": 91.537,
+ "Wrst": 5223.9,
+ "StDev": 1644.1
+ },
+ {
+ "count": 13,
+ "host": "ae7.ter2.sea1.us.zip.zayo.com (64.125.19.197)",
+ "ASN": "AS6461",
+ "Loss%": 0.0,
+ "Snt": 10,
+ "Last": 91.212,
+ "Avg": 112.17,
+ "Best": 90.979,
+ "Wrst": 178.26,
+ "StDev": 30.086
+ },
+ {
+ "count": 14,
+ "host": "208.185.33.178.IDIA-369396-ZYO.zip.zayo.com (208.185.33.178)",
+ "ASN": "AS6461",
+ "Loss%": 0.0,
+ "Snt": 10,
+ "Last": 103.95,
+ "Avg": 104.46,
+ "Best": 90.349,
+ "Wrst": 136.62,
+ "StDev": 15.726
+ },
+ {
+ "count": 15,
+ "host": "168.245.215.250",
+ "ASN": "AS55039",
+ "Loss%": 0.0,
+ "Snt": 10,
+ "Last": 85.672,
+ "Avg": 95.289,
+ "Best": 84.352,
+ "Wrst": 156.16,
+ "StDev": 21.621
+ },
+ {
+ "count": 16,
+ "host": "???",
+ "ASN": "AS???",
+ "Loss%": 100.0,
+ "Snt": 10,
+ "Last": 0.0,
+ "Avg": 0.0,
+ "Best": 0.0,
+ "Wrst": 0.0,
+ "StDev": 0.0
+ }
+ ]
+ }
+}
diff --git a/tests/data/nmaprun1.xml b/tests/data/nmaprun1.xml
new file mode 100644
index 0000000..c5fed6c
--- /dev/null
+++ b/tests/data/nmaprun1.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE nmaprun>
+<?xml-stylesheet href="file:///usr/bin/../share/nmap/nmap.xsl" type="text/xsl"?>
+<!-- Nmap 7.80 scan initiated Wed Mar 4 12:59:08 2026 as: nmap -O -A -Pn -sV -p 22-1000,11000,1100,3389,61232 -oX - 108.171.53.1 -->
+<nmaprun scanner="nmap" args="nmap -O -A -Pn -sV -p 22-1000,11000,1100,3389,61232 -oX - 108.171.53.1" start="1772650748"
+ startstr="Wed Mar 4 12:59:08 2026" version="7.80" xmloutputversion="1.04">
+ <scaninfo type="syn" protocol="tcp" numservices="983" services="22-1000,1100,3389,11000,61232"/>
+ <scaninfo type="syn" protocol="udp" numservices="983" services="69,420"/>
+ <verbose level="0"/>
+ <debugging level="0"/>
+ <host starttime="1772650748" endtime="1772650901">
+ <status state="up" reason="user-set" reason_ttl="0"/>
+ <address addr="108.171.53.1" addrtype="ipv4"/>
+ <hostnames>
+ <hostname name="108-171-53-1.aceips.com" type="PTR"/>
+ </hostnames>
+ <ports>
+ <extraports state="filtered" count="982">
+ <extrareasons reason="no-responses" count="982"/>
+ </extraports>
+ <port protocol="tcp" portid="61232">
+ <state state="open" reason="syn-ack" reason_ttl="47"/>
+ <service name="socks5" extrainfo="Username/password authentication required" method="probed" conf="10"/>
+ <script id="socks-auth-info" output="&#xa; Username and password">
+ <table>
+ <elem key="name">Username and password</elem>
+ <elem key="method">2</elem>
+ </table>
+ </script>
+ </port>
+ </ports>
+ <os>
+ <portused state="open" proto="tcp" portid="61232"/>
+ </os>
+ <uptime seconds="4063775" lastboot="Fri Jan 16 12:12:06 2026"/>
+ <distance value="21"/>
+ <tcpsequence index="263" difficulty="Good luck!" values="B67613E,2F0160C6,27FA849E,3B16FC3A,916ADEAF,18293FD7"/>
+ <ipidsequence class="All zeros" values="0,0,0,0,0,0"/>
+ <tcptssequence class="1000HZ" values="F2383963,F23839C0,F2383A24,F2383A8C,F2383AED,F2383B54"/>
+ <trace port="61232" proto="tcp">
+ <hop ttl="1" ipaddr="192.168.86.1" rtt="3.83" host="_gateway"/>
+ <hop ttl="2" ipaddr="192.168.100.1" rtt="4.90"/>
+ <hop ttl="3" ipaddr="10.125.64.1" rtt="6.01"/>
+ <hop ttl="4" ipaddr="10.180.25.105" rtt="14.52"/>
+ <hop ttl="5" ipaddr="10.180.25.106" rtt="16.47"/>
+ <hop ttl="6" ipaddr="10.180.25.81" rtt="28.56"/>
+ <hop ttl="7" ipaddr="62.115.192.20" rtt="17.17" host="gdl-b2-link.ip.twelve99.net"/>
+ <hop ttl="8" ipaddr="62.115.140.131" rtt="29.56" host="mny-b4-link.ip.twelve99.net"/>
+ <hop ttl="9" ipaddr="62.115.124.12" rtt="27.68" host="mdc-b2-link.ip.twelve99.net"/>
+ <hop ttl="10" ipaddr="62.115.126.144" rtt="34.92" host="hou-b3-link.ip.twelve99.net"/>
+ <hop ttl="11" ipaddr="62.115.116.47" rtt="48.42" host="atl-b24-link.ip.twelve99.net"/>
+ <hop ttl="13" ipaddr="62.115.137.132" rtt="62.35" host="ash-bb2-link.ip.twelve99.net"/>
+ <hop ttl="14" ipaddr="62.115.139.34" rtt="67.51" host="nyk-bb5-link.ip.twelve99.net"/>
+ <hop ttl="16" ipaddr="62.115.136.13" rtt="64.75" host="ewr-b15-link.ip.twelve99.net"/>
+ <hop ttl="17" ipaddr="62.115.136.13" rtt="67.87" host="ewr-b15-link.ip.twelve99.net"/>
+ <hop ttl="19" ipaddr="75.76.132.68" rtt="72.32" host="hge0-1-0-6.aggr1.jfk.ny.rcn.net"/>
+ <hop ttl="20" ipaddr="207.237.73.98" rtt="68.13"/>
+ <hop ttl="21" ipaddr="108.171.53.1" rtt="64.76" host="108-171-53-1.aceips.com"/>
+ </trace>
+ <times srtt="54719" rttvar="23423" to="148411"/>
+ </host>
+ <runstats>
+ <finished time="1772650901" timestr="Wed Mar 4 13:01:41 2026" elapsed="153.06"
+ summary="Nmap done at Wed Mar 4 13:01:41 2026; 1 IP address (1 host up) scanned in 153.06 seconds"
+ exit="success"/>
+ <hosts up="1" down="0" total="1"/>
+ </runstats>
+</nmaprun>
diff --git a/tests/data/nmaprun2.xml b/tests/data/nmaprun2.xml
new file mode 100644
index 0000000..932896c
--- /dev/null
+++ b/tests/data/nmaprun2.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE nmaprun>
+<?xml-stylesheet href="file:///usr/bin/../share/nmap/nmap.xsl" type="text/xsl"?>
+<!-- Nmap 7.80 scan initiated Tue Mar 3 17:50:03 2026 as: nmap -T4 -A -oX - scanme.nmap.org -->
+<nmaprun scanner="nmap" args="nmap -T4 -A -oX - scanme.nmap.org" start="1772581803" startstr="Tue Mar 3 17:50:03 2026"
+ version="7.80" xmloutputversion="1.04">
+ <scaninfo type="connect" protocol="tcp" numservices="1000"
+ services="1,3-4,6-7,9,13,17,19-26,30,32-33,37,42-43,49,53,70,79-85,88-90,99-100,106,109-111,113,119,125,135,139,143-144,146,161,163,179,199,211-212,222,254-256,259,264,280,301,306,311,340,366,389,406-407,416-417,425,427,443-445,458,464-465,481,497,500,512-515,524,541,543-545,548,554-555,563,587,593,616-617,625,631,636,646,648,666-668,683,687,691,700,705,711,714,720,722,726,749,765,777,783,787,800-801,808,843,873,880,888,898,900-903,911-912,981,987,990,992-993,995,999-1002,1007,1009-1011,1021-1100,1102,1104-1108,1110-1114,1117,1119,1121-1124,1126,1130-1132,1137-1138,1141,1145,1147-1149,1151-1152,1154,1163-1166,1169,1174-1175,1183,1185-1187,1192,1198-1199,1201,1213,1216-1218,1233-1234,1236,1244,1247-1248,1259,1271-1272,1277,1287,1296,1300-1301,1309-1311,1322,1328,1334,1352,1417,1433-1434,1443,1455,1461,1494,1500-1501,1503,1521,1524,1533,1556,1580,1583,1594,1600,1641,1658,1666,1687-1688,1700,1717-1721,1723,1755,1761,1782-1783,1801,1805,1812,1839-1840,1862-1864,1875,1900,1914,1935,1947,1971-1972,1974,1984,1998-2010,2013,2020-2022,2030,2033-2035,2038,2040-2043,2045-2049,2065,2068,2099-2100,2103,2105-2107,2111,2119,2121,2126,2135,2144,2160-2161,2170,2179,2190-2191,2196,2200,2222,2251,2260,2288,2301,2323,2366,2381-2383,2393-2394,2399,2401,2492,2500,2522,2525,2557,2601-2602,2604-2605,2607-2608,2638,2701-2702,2710,2717-2718,2725,2800,2809,2811,2869,2875,2909-2910,2920,2967-2968,2998,3000-3001,3003,3005-3007,3011,3013,3017,3030-3031,3052,3071,3077,3128,3168,3211,3221,3260-3261,3268-3269,3283,3300-3301,3306,3322-3325,3333,3351,3367,3369-3372,3389-3390,3404,3476,3493,3517,3527,3546,3551,3580,3659,3689-3690,3703,3737,3766,3784,3800-3801,3809,3814,3826-3828,3851,3869,3871,3878,3880,3889,3905,3914,3918,3920,3945,3971,3986,3995,3998,4000-4006,4045,4111,4125-4126,4129,4224,4242,4279,4321,4343,4443-4446,4449,4550,4567,4662,4848,4899-4900,4998,5000-5004,5009,5030,5033,5050-5051,5054,5060-5061,5080,5087,5100-5102,5120,5190,5200,5214,5221-5222,5225-5226,5269,5280,5298,5357,5405,5414,5431-5432,5440,5500,5510,5544,5550,5555,5560,5566,5631,5633,5666,5678-5679,5718,5730,5800-5802,5810-5811,5815,5822,5825,5850,5859,5862,5877,5900-5904,5906-5907,5910-5911,5915,5922,5925,5950,5952,5959-5963,5987-5989,5998-6007,6009,6025,6059,6100-6101,6106,6112,6123,6129,6156,6346,6389,6502,6510,6543,6547,6565-6567,6580,6646,6666-6669,6689,6692,6699,6779,6788-6789,6792,6839,6881,6901,6969,7000-7002,7004,7007,7019,7025,7070,7100,7103,7106,7200-7201,7402,7435,7443,7496,7512,7625,7627,7676,7741,7777-7778,7800,7911,7920-7921,7937-7938,7999-8002,8007-8011,8021-8022,8031,8042,8045,8080-8090,8093,8099-8100,8180-8181,8192-8194,8200,8222,8254,8290-8292,8300,8333,8383,8400,8402,8443,8500,8600,8649,8651-8652,8654,8701,8800,8873,8888,8899,8994,9000-9003,9009-9011,9040,9050,9071,9080-9081,9090-9091,9099-9103,9110-9111,9200,9207,9220,9290,9415,9418,9485,9500,9502-9503,9535,9575,9593-9595,9618,9666,9876-9878,9898,9900,9917,9929,9943-9944,9968,9998-10004,10009-10010,10012,10024-10025,10082,10180,10215,10243,10566,10616-10617,10621,10626,10628-10629,10778,11110-11111,11967,12000,12174,12265,12345,13456,13722,13782-13783,14000,14238,14441-14442,15000,15002-15004,15660,15742,16000-16001,16012,16016,16018,16080,16113,16992-16993,17877,17988,18040,18101,18988,19101,19283,19315,19350,19780,19801,19842,20000,20005,20031,20221-20222,20828,21571,22939,23502,24444,24800,25734-25735,26214,27000,27352-27353,27355-27356,27715,28201,30000,30718,30951,31038,31337,32768-32785,33354,33899,34571-34573,35500,38292,40193,40911,41511,42510,44176,44442-44443,44501,45100,48080,49152-49161,49163,49165,49167,49175-49176,49400,49999-50003,50006,50300,50389,50500,50636,50800,51103,51493,52673,52822,52848,52869,54045,54328,55055-55056,55555,55600,56737-56738,57294,57797,58080,60020,60443,61532,61900,62078,63331,64623,64680,65000,65129,65389"/>
+ <verbose level="0"/>
+ <debugging level="0"/>
+ <host starttime="1772581804" endtime="1772581818">
+ <status state="up" reason="syn-ack" reason_ttl="0"/>
+ <address addr="45.33.32.156" addrtype="ipv4"/>
+ <hostnames>
+ <hostname name="scanme.nmap.org" type="user"/>
+ <hostname name="scanme.nmap.org" type="PTR"/>
+ </hostnames>
+ <ports>
+ <extraports state="closed" count="995">
+ <extrareasons reason="conn-refused" count="995"/>
+ </extraports>
+ <port protocol="tcp" portid="22">
+ <state state="open" reason="syn-ack" reason_ttl="0"/>
+ <service name="ssh" product="OpenSSH" version="6.6.1p1 Ubuntu 2ubuntu2.13"
+ extrainfo="Ubuntu Linux; protocol 2.0" ostype="Linux" method="probed" conf="10">
+ <cpe>cpe:/a:openbsd:openssh:6.6.1p1</cpe>
+ <cpe>cpe:/o:linux:linux_kernel</cpe>
+ </service>
+ <script id="ssh-hostkey"
+ output="&#xa; 1024 ac:00:a0:1a:82:ff:cc:55:99:dc:67:2b:34:97:6b:75 (DSA)&#xa; 2048 20:3d:2d:44:62:2a:b0:5a:9d:b5:b3:05:14:c2:a6:b2 (RSA)&#xa; 256 96:02:bb:5e:57:54:1c:4e:45:2f:56:4c:4a:24:b2:57 (ECDSA)&#xa; 256 33:fa:91:0f:e0:e1:7b:1f:6d:05:a2:b0:f1:54:41:56 (ED25519)">
+ <table>
+ <elem key="bits">1024</elem>
+ <elem key="type">ssh-dss</elem>
+ <elem key="key">
+ AAAAB3NzaC1kc3MAAACBAOe8o59vFWZGaBmGPVeJBObEfi1AR8yEUYC/Ufkku3sKhGF7wM2m2ujIeZDK5vqeC0S5EN2xYo6FshCP4FQRYeTxD17nNO4PhwW65qAjDRRU0uHFfSAh5wk+vt4yQztOE++sTd1G9OBLzA8HO99qDmCAxb3zw+GQDEgPjzgyzGZ3AAAAFQCBmE1vROP8IaPkUmhM5xLFta/xHwAAAIEA3EwRfaeOPLL7TKDgGX67Lbkf9UtdlpCdC4doMjGgsznYMwWH6a7Lj3vi4/KmeZZdix6FMdFqq+2vrfT1DRqx0RS0XYdGxnkgS+2g333WYCrUkDCn6RPUWR/1TgGMPHCj7LWCa1ZwJwLWS2KX288Pa2gLOWuhZm2VYKSQx6NEDOIAAACBANxIfprSdBdbo4Ezrh6/X6HSvrhjtZ7MouStWaE714ByO5bS2coM9CyaCwYyrE5qzYiyIfb+1BG3O5nVdDuN95sQ/0bAdBKlkqLFvFqFjVbETF0ri3v97w6MpUawfF75ouDrQ4xdaUOLLEWTso6VFJcM6Jg9bDl0FA0uLZUSDEHL
+ </elem>
+ <elem key="fingerprint">ac00a01a82ffcc5599dc672b34976b75</elem>
+ </table>
+ <table>
+ <elem key="bits">2048</elem>
+ <elem key="type">ssh-rsa</elem>
+ <elem key="key">
+ AAAAB3NzaC1yc2EAAAADAQABAAABAQC6afooTZ9mVUGFNEhkMoRR1Btzu64XXwElhCsHw/zVlIx/HXylNbb9+11dm2VgJQ21pxkWDs+L6+EbYyDnvRURTrMTgHL0xseB0EkNqexs9hYZSiqtMx4jtGNtHvsMxZnbxvVUk2dasWvtBkn8J5JagSbzWTQo4hjKMOI1SUlXtiKxAs2F8wiq2EdSuKw/KNk8GfIp1TA+8ccGeAtnsVptTJ4D/8MhAWsROkQzOowQvnBBz2/8ecEvoMScaf+kDfNQowK3gENtSSOqYw9JLOza6YJBPL/aYuQQ0nJ74Rr5vL44aNIlrGI9jJc2x0bV7BeNA5kVuXsmhyfWbbkB8yGd
+ </elem>
+ <elem key="fingerprint">203d2d44622ab05a9db5b30514c2a6b2</elem>
+ </table>
+ <table>
+ <elem key="bits">256</elem>
+ <elem key="type">ecdsa-sha2-nistp256</elem>
+ <elem key="key">
+ AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMD46g67x6yWNjjQJnXhiz/TskHrqQ0uPcOspFrIYW382uOGzmWDZCFV8FbFwQyH90u+j0Qr1SGNAxBZMhOQ8pc=
+ </elem>
+ <elem key="fingerprint">9602bb5e57541c4e452f564c4a24b257</elem>
+ </table>
+ <table>
+ <elem key="bits">256</elem>
+ <elem key="type">ssh-ed25519</elem>
+ <elem key="key">AAAAC3NzaC1lZDI1NTE5AAAAILzVjfIyIHfXyRd8jVBaVT8Yvk/UvHh5Afvho8sGciG7</elem>
+ <elem key="fingerprint">33fa910fe0e17b1f6d05a2b0f1544156</elem>
+ </table>
+ </script>
+ </port>
+ <port protocol="tcp" portid="25">
+ <state state="filtered" reason="no-response" reason_ttl="0"/>
+ <service name="smtp" method="table" conf="3"/>
+ </port>
+ <port protocol="tcp" portid="80">
+ <state state="open" reason="syn-ack" reason_ttl="0"/>
+ <service name="http" product="Apache httpd" version="2.4.7" extrainfo="(Ubuntu)" method="probed"
+ conf="10">
+ <cpe>cpe:/a:apache:http_server:2.4.7</cpe>
+ </service>
+ <script id="http-server-header" output="Apache/2.4.7 (Ubuntu)">
+ <elem>Apache/2.4.7 (Ubuntu)</elem>
+ </script>
+ <script id="http-title" output="Go ahead and ScanMe!">
+ <elem key="title">Go ahead and ScanMe!</elem>
+ </script>
+ </port>
+ <port protocol="tcp" portid="9929">
+ <state state="open" reason="syn-ack" reason_ttl="0"/>
+ <service name="nping-echo" product="Nping echo" method="probed" conf="10"/>
+ </port>
+ <port protocol="tcp" portid="31337">
+ <state state="open" reason="syn-ack" reason_ttl="0"/>
+ <service name="tcpwrapped" method="probed" conf="8"/>
+ </port>
+ </ports>
+ <os>
+ <portused state="open" proto="tcp" portid="22"/>
+ <portused state="closed" proto="tcp" portid="1"/>
+ <portused state="closed" proto="udp" portid="31994"/>
+ <osmatch name="Linux 2.6.38 - 3.0" accuracy="100" line="43893">
+ <osclass type="general purpose" vendor="Linux" osfamily="Linux" osgen="2.6.X" accuracy="100">
+ <cpe>cpe:/o:linux:linux_kernel:2.6</cpe>
+ </osclass>
+ <osclass type="general purpose" vendor="Linux" osfamily="Linux" osgen="3.X" accuracy="100">
+ <cpe>cpe:/o:linux:linux_kernel:3</cpe>
+ </osclass>
+ </osmatch>
+ <osfingerprint
+ fingerprint=" SEQ(SP=C5%GCD=1%ISR=C7%TI=Z%II=I%TS=8) ECN(R=Y%DF=Y%T=40%W=16D0%O=M5B4NNSNW2%CC=N%Q=) T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=) T2(R=N) T3(R=Y%DF=Y%T=40%W=16A0%S=O%A=S+%F=AS%O=M5B4ST11NW2%RD=0%Q=) T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=) T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=) U1(R=Y%DF=N%T=40%TOS=C0%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUL=G%RUD=G) IE(R=Y%DFI=N%T=40%TOSI=S%CD=S%SI=S%DLI=S) "/>
+ </os>
+ <hostscript>
+ <script id="sql-injection" output="Possible SQL injection vulnerability detected:
+ URI: /index.php?id=1'
+ Payload: id=1' OR '1'='1
+ Output: SQL error detected"/>
+ </hostscript>
+ <times srtt="90053" rttvar="8723" to="124945"/>
+ </host>
+ <runstats>
+ <finished time="1772581818" timestr="Tue Mar 3 17:50:18 2026" elapsed="14.44"
+ summary="Nmap done at Tue Mar 3 17:50:18 2026; 1 IP address (1 host up) scanned in 14.44 seconds"
+ exit="success"/>
+ <hosts up="1" down="0" total="1"/>
+ </runstats>
+</nmaprun>
diff --git a/tests/managers/network/__init__.py b/tests/managers/network/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/managers/network/__init__.py
diff --git a/tests/managers/network/test_label.py b/tests/managers/network/test_label.py
new file mode 100644
index 0000000..5b9a790
--- /dev/null
+++ b/tests/managers/network/test_label.py
@@ -0,0 +1,202 @@
+import ipaddress
+
+import faker
+import pytest
+from psycopg.errors import UniqueViolation
+from pydantic import ValidationError
+
+from generalresearch.managers.network.label import IPLabelManager
+from generalresearch.models.network.label import (
+ IPLabel,
+ IPLabelKind,
+ IPLabelSource,
+ IPLabelMetadata,
+)
+from generalresearch.models.thl.ipinfo import normalize_ip
+
+fake = faker.Faker()
+
+
+@pytest.fixture
+def ip_label(utc_now) -> IPLabel:
+ ip = ipaddress.IPv6Network((fake.ipv6(), 64), strict=False)
+ return IPLabel(
+ label_kind=IPLabelKind.VPN,
+ labeled_at=utc_now,
+ source=IPLabelSource.INTERNAL_USE,
+ provider="GeoNodE",
+ created_at=utc_now,
+ ip=ip,
+ metadata=IPLabelMetadata(services=["RDP"])
+ )
+
+
+def test_model(utc_now):
+ ip = fake.ipv4_public()
+ lbl = IPLabel(
+ label_kind=IPLabelKind.VPN,
+ labeled_at=utc_now,
+ source=IPLabelSource.INTERNAL_USE,
+ provider="GeoNodE",
+ created_at=utc_now,
+ ip=ip,
+ )
+ assert lbl.ip.prefixlen == 32
+ print(f"{lbl.ip=}")
+
+ ip = ipaddress.IPv4Network((ip, 24), strict=False)
+ lbl = IPLabel(
+ label_kind=IPLabelKind.VPN,
+ labeled_at=utc_now,
+ source=IPLabelSource.INTERNAL_USE,
+ provider="GeoNodE",
+ created_at=utc_now,
+ ip=ip,
+ )
+ print(f"{lbl.ip=}")
+
+ with pytest.raises(ValidationError, match="IPv6 network must be /64 or larger"):
+ IPLabel(
+ label_kind=IPLabelKind.VPN,
+ labeled_at=utc_now,
+ source=IPLabelSource.INTERNAL_USE,
+ provider="GeoNodE",
+ created_at=utc_now,
+ ip=fake.ipv6(),
+ )
+
+ ip = ipaddress.IPv6Network((fake.ipv6(), 64), strict=False)
+ lbl = IPLabel(
+ label_kind=IPLabelKind.VPN,
+ labeled_at=utc_now,
+ source=IPLabelSource.INTERNAL_USE,
+ provider="GeoNodE",
+ created_at=utc_now,
+ ip=ip,
+ )
+ print(f"{lbl.ip=}")
+
+ ip = ipaddress.IPv6Network((ip.network_address, 48), strict=False)
+ lbl = IPLabel(
+ label_kind=IPLabelKind.VPN,
+ labeled_at=utc_now,
+ source=IPLabelSource.INTERNAL_USE,
+ provider="GeoNodE",
+ created_at=utc_now,
+ ip=ip,
+ )
+ print(f"{lbl.ip=}")
+
+
+def test_create(iplabel_manager: IPLabelManager, ip_label: IPLabel):
+ iplabel_manager.create(ip_label)
+
+ with pytest.raises(
+ UniqueViolation, match="duplicate key value violates unique constraint"
+ ):
+ iplabel_manager.create(ip_label)
+
+
+def test_filter(iplabel_manager: IPLabelManager, ip_label: IPLabel, utc_hour_ago):
+ res = iplabel_manager.filter(ips=[ip_label.ip])
+ assert len(res) == 0
+
+ iplabel_manager.create(ip_label)
+ res = iplabel_manager.filter(ips=[ip_label.ip])
+ assert len(res) == 1
+
+ out = res[0]
+ assert out == ip_label
+
+ res = iplabel_manager.filter(ips=[ip_label.ip], labeled_after=utc_hour_ago)
+ assert len(res) == 1
+
+ ip_label2 = ip_label.model_copy()
+ ip_label2.ip = fake.ipv4_public()
+ iplabel_manager.create(ip_label2)
+ res = iplabel_manager.filter(ips=[ip_label.ip, ip_label2.ip])
+ assert len(res) == 2
+
+
+def test_filter_network(
+ iplabel_manager: IPLabelManager, ip_label: IPLabel, utc_hour_ago
+):
+ print(ip_label)
+ ip_label = ip_label.model_copy()
+ ip_label.ip = ipaddress.IPv6Network((fake.ipv6(), 64), strict=False)
+
+ iplabel_manager.create(ip_label)
+ res = iplabel_manager.filter(ips=[ip_label.ip])
+ assert len(res) == 1
+
+ out = res[0]
+ assert out == ip_label
+
+ res = iplabel_manager.filter(ips=[ip_label.ip], labeled_after=utc_hour_ago)
+ assert len(res) == 1
+
+ ip_label2 = ip_label.model_copy()
+ ip_label2.ip = fake.ipv4_public()
+ iplabel_manager.create(ip_label2)
+ res = iplabel_manager.filter(ips=[ip_label.ip, ip_label2.ip])
+ assert len(res) == 2
+
+
+def test_network(iplabel_manager: IPLabelManager, utc_now):
+ # This is a fully-specific /128 ipv6 address.
+ # e.g. '51b7:b38d:8717:6c5b:cd3e:f5c3:3aba:17d'
+ ip = fake.ipv6()
+ # Generally, we'd want to annotate the /64 network
+ # e.g. '51b7:b38d:8717:6c5b::/64'
+ ip_64 = ipaddress.IPv6Network((ip, 64), strict=False)
+
+ label = IPLabel(
+ label_kind=IPLabelKind.VPN,
+ labeled_at=utc_now,
+ source=IPLabelSource.INTERNAL_USE,
+ provider="GeoNodE",
+ created_at=utc_now,
+ ip=ip_64,
+ )
+ iplabel_manager.create(label)
+
+ # If I query for the /128 directly, I won't find it
+ res = iplabel_manager.filter(ips=[ip])
+ assert len(res) == 0
+
+ # If I query for the /64 network I will
+ res = iplabel_manager.filter(ips=[ip_64])
+ assert len(res) == 1
+
+ # Or, I can query for the /128 ip IN a network
+ res = iplabel_manager.filter(ip_in_network=ip)
+ assert len(res) == 1
+
+
+def test_label_cidr_and_ipinfo(
+ iplabel_manager: IPLabelManager, ip_information_factory, ip_geoname, utc_now
+):
+ # We have network_iplabel.ip as a cidr col and
+ # thl_ipinformation.ip as a inet col. Make sure we can join appropriately
+ ip = fake.ipv6()
+ ip_information_factory(ip=ip, geoname=ip_geoname)
+ # We normalize for storage into ipinfo table
+ ip_norm, prefix = normalize_ip(ip)
+
+ # Test with a larger network
+ ip_48 = ipaddress.IPv6Network((ip, 48), strict=False)
+ print(f"{ip=}")
+ print(f"{ip_norm=}")
+ print(f"{ip_48=}")
+ label = IPLabel(
+ label_kind=IPLabelKind.VPN,
+ labeled_at=utc_now,
+ source=IPLabelSource.INTERNAL_USE,
+ provider="GeoNodE",
+ created_at=utc_now,
+ ip=ip_48,
+ )
+ iplabel_manager.create(label)
+
+ res = iplabel_manager.test_join(ip_norm)
+ print(res)
diff --git a/tests/managers/network/test_tool_run.py b/tests/managers/network/test_tool_run.py
new file mode 100644
index 0000000..a815809
--- /dev/null
+++ b/tests/managers/network/test_tool_run.py
@@ -0,0 +1,25 @@
+def test_create_tool_run_from_nmap_run(nmap_run, toolrun_manager):
+
+ toolrun_manager.create_nmap_run(nmap_run)
+
+ run_out = toolrun_manager.get_nmap_run(nmap_run.id)
+
+ assert nmap_run == run_out
+
+
+def test_create_tool_run_from_rdns_run(rdns_run, toolrun_manager):
+
+ toolrun_manager.create_rdns_run(rdns_run)
+
+ run_out = toolrun_manager.get_rdns_run(rdns_run.id)
+
+ assert rdns_run == run_out
+
+
+def test_create_tool_run_from_mtr_run(mtr_run, toolrun_manager):
+
+ toolrun_manager.create_mtr_run(mtr_run)
+
+ run_out = toolrun_manager.get_mtr_run(mtr_run.id)
+
+ assert mtr_run == run_out
diff --git a/tests/models/network/__init__.py b/tests/models/network/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/models/network/__init__.py
diff --git a/tests/models/network/test_mtr.py b/tests/models/network/test_mtr.py
new file mode 100644
index 0000000..2965300
--- /dev/null
+++ b/tests/models/network/test_mtr.py
@@ -0,0 +1,26 @@
+from generalresearch.models.network.mtr.execute import execute_mtr
+import faker
+
+from generalresearch.models.network.tool_run import ToolName, ToolClass
+
+fake = faker.Faker()
+
+
+def test_execute_mtr(toolrun_manager):
+ ip = "65.19.129.53"
+
+ run = execute_mtr(ip=ip, report_cycles=3)
+ assert run.tool_name == ToolName.MTR
+ assert run.tool_class == ToolClass.TRACEROUTE
+ assert run.ip == ip
+ result = run.parsed
+
+ last_hop = result.hops[-1]
+ assert last_hop.asn == 6939
+ assert last_hop.domain == "grlengine.com"
+
+ last_hop_1 = result.hops[-2]
+ assert last_hop_1.asn == 6939
+ assert last_hop_1.domain == "he.net"
+
+ toolrun_manager.create_mtr_run(run)
diff --git a/tests/models/network/test_nmap.py b/tests/models/network/test_nmap.py
new file mode 100644
index 0000000..0be98d4
--- /dev/null
+++ b/tests/models/network/test_nmap.py
@@ -0,0 +1,29 @@
+import subprocess
+
+from generalresearch.models.network.definitions import IPProtocol
+from generalresearch.models.network.nmap.execute import execute_nmap
+import faker
+
+from generalresearch.models.network.nmap.result import PortState
+from generalresearch.models.network.tool_run import ToolName, ToolClass
+
+fake = faker.Faker()
+
+
+def resolve(host):
+ return subprocess.check_output(["dig", host, "+short"]).decode().strip()
+
+
+def test_execute_nmap_scanme(toolrun_manager):
+ ip = resolve("scanme.nmap.org")
+
+ run = execute_nmap(ip=ip, top_ports=None, ports="20-30", enable_advanced=False)
+ assert run.tool_name == ToolName.NMAP
+ assert run.tool_class == ToolClass.PORT_SCAN
+ assert run.ip == ip
+ result = run.parsed
+
+ port22 = result._port_index[(IPProtocol.TCP, 22)]
+ assert port22.state == PortState.OPEN
+
+ toolrun_manager.create_nmap_run(run)
diff --git a/tests/models/network/test_nmap_parser.py b/tests/models/network/test_nmap_parser.py
new file mode 100644
index 0000000..96d7b37
--- /dev/null
+++ b/tests/models/network/test_nmap_parser.py
@@ -0,0 +1,22 @@
+import os
+
+import pytest
+
+from generalresearch.models.network.nmap.parser import parse_nmap_xml
+
+@pytest.fixture
+def nmap_raw_output_2(request) -> str:
+ fp = os.path.join(request.config.rootpath, "data/nmaprun2.xml")
+ with open(fp, "r") as f:
+ data = f.read()
+ return data
+
+
+def test_nmap_xml_parser(nmap_raw_output, nmap_raw_output_2):
+ n = parse_nmap_xml(nmap_raw_output)
+ assert n.tcp_open_ports == [61232]
+ assert len(n.trace.hops) == 18
+
+ n = parse_nmap_xml(nmap_raw_output_2)
+ assert n.tcp_open_ports == [22, 80, 9929, 31337]
+ assert n.trace is None
diff --git a/tests/models/network/test_rdns.py b/tests/models/network/test_rdns.py
new file mode 100644
index 0000000..e56c494
--- /dev/null
+++ b/tests/models/network/test_rdns.py
@@ -0,0 +1,33 @@
+from generalresearch.models.network.rdns.execute import execute_rdns
+import faker
+
+from generalresearch.models.network.tool_run import ToolName, ToolClass
+
+fake = faker.Faker()
+
+
+def test_execute_rdns_grl(toolrun_manager):
+ ip = "65.19.129.53"
+ run = execute_rdns(ip=ip)
+ assert run.tool_name == ToolName.DIG
+ assert run.tool_class == ToolClass.RDNS
+ assert run.ip == ip
+ result = run.parsed
+ assert result.primary_hostname == "in1-smtp.grlengine.com"
+ assert result.primary_domain == "grlengine.com"
+ assert result.hostname_count == 1
+
+ toolrun_manager.create_rdns_run(run)
+
+
+def test_execute_rdns_none(toolrun_manager):
+ ip = fake.ipv6()
+ run = execute_rdns(ip)
+ result = run.parsed
+
+ assert result.primary_hostname is None
+ assert result.primary_domain is None
+ assert result.hostname_count == 0
+ assert result.hostnames == []
+
+ toolrun_manager.create_rdns_run(run)