lanscape 1.3.1a8__tar.gz → 1.3.2a6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of lanscape might be problematic. Click here for more details.
- lanscape-1.3.2a6/MANIFEST.in +4 -0
- {lanscape-1.3.1a8/src/lanscape.egg-info → lanscape-1.3.2a6}/PKG-INFO +4 -3
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/__init__.py +4 -1
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/__main__.py +4 -1
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/css/style.css +1 -1
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/templates/core/scripts.html +1 -1
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/templates/info.html +1 -1
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/templates/main.html +6 -4
- {lanscape-1.3.1a8 → lanscape-1.3.2a6/lanscape.egg-info}/PKG-INFO +4 -3
- lanscape-1.3.2a6/lanscape.egg-info/SOURCES.txt +51 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape.egg-info/requires.txt +1 -1
- {lanscape-1.3.1a8 → lanscape-1.3.2a6}/pyproject.toml +31 -26
- {lanscape-1.3.1a8/src/lanscape → lanscape-1.3.2a6}/tests/test_api.py +38 -36
- {lanscape-1.3.1a8/src/lanscape → lanscape-1.3.2a6}/tests/test_env.py +8 -11
- lanscape-1.3.2a6/tests/test_library.py +84 -0
- lanscape-1.3.2a6/tests/test_utils.py +86 -0
- lanscape-1.3.1a8/MANIFEST.in +0 -4
- lanscape-1.3.1a8/src/lanscape/libraries/app_scope.py +0 -70
- lanscape-1.3.1a8/src/lanscape/libraries/decorators.py +0 -75
- lanscape-1.3.1a8/src/lanscape/libraries/errors.py +0 -29
- lanscape-1.3.1a8/src/lanscape/libraries/ip_parser.py +0 -65
- lanscape-1.3.1a8/src/lanscape/libraries/logger.py +0 -42
- lanscape-1.3.1a8/src/lanscape/libraries/mac_lookup.py +0 -69
- lanscape-1.3.1a8/src/lanscape/libraries/net_tools.py +0 -480
- lanscape-1.3.1a8/src/lanscape/libraries/port_manager.py +0 -59
- lanscape-1.3.1a8/src/lanscape/libraries/runtime_args.py +0 -44
- lanscape-1.3.1a8/src/lanscape/libraries/service_scan.py +0 -51
- lanscape-1.3.1a8/src/lanscape/libraries/subnet_scan.py +0 -373
- lanscape-1.3.1a8/src/lanscape/libraries/version_manager.py +0 -54
- lanscape-1.3.1a8/src/lanscape/libraries/web_browser.py +0 -141
- lanscape-1.3.1a8/src/lanscape/resources/mac_addresses/convert_csv.py +0 -27
- lanscape-1.3.1a8/src/lanscape/resources/ports/convert_csv.py +0 -27
- lanscape-1.3.1a8/src/lanscape/tests/__init__.py +0 -3
- lanscape-1.3.1a8/src/lanscape/tests/_helpers.py +0 -15
- lanscape-1.3.1a8/src/lanscape/tests/test_library.py +0 -53
- lanscape-1.3.1a8/src/lanscape/ui/app.py +0 -122
- lanscape-1.3.1a8/src/lanscape/ui/blueprints/__init__.py +0 -7
- lanscape-1.3.1a8/src/lanscape/ui/blueprints/api/__init__.py +0 -5
- lanscape-1.3.1a8/src/lanscape/ui/blueprints/api/port.py +0 -27
- lanscape-1.3.1a8/src/lanscape/ui/blueprints/api/scan.py +0 -69
- lanscape-1.3.1a8/src/lanscape/ui/blueprints/api/tools.py +0 -30
- lanscape-1.3.1a8/src/lanscape/ui/blueprints/web/__init__.py +0 -5
- lanscape-1.3.1a8/src/lanscape/ui/blueprints/web/routes.py +0 -74
- lanscape-1.3.1a8/src/lanscape/ui/main.py +0 -138
- lanscape-1.3.1a8/src/lanscape.egg-info/SOURCES.txt +0 -76
- {lanscape-1.3.1a8 → lanscape-1.3.2a6}/LICENSE +0 -0
- {lanscape-1.3.1a8 → lanscape-1.3.2a6}/README.md +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/resources/mac_addresses/mac_db.json +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/resources/ports/full.json +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/resources/ports/large.json +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/resources/ports/medium.json +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/resources/ports/small.json +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/resources/services/definitions.jsonc +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/img/ico/android-chrome-192x192.png +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/img/ico/android-chrome-512x512.png +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/img/ico/apple-touch-icon.png +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/img/ico/favicon-16x16.png +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/img/ico/favicon-32x32.png +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/img/ico/favicon.ico +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/img/ico/site.webmanifest +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/js/core.js +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/js/layout-sizing.js +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/js/main.js +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/js/on-tab-close.js +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/js/quietReload.js +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/js/shutdown-server.js +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/js/subnet-info.js +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/js/subnet-selector.js +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/static/lanscape.webmanifest +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/templates/base.html +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/templates/core/head.html +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/templates/error.html +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/templates/scan/export.html +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/templates/scan/ip-table-row.html +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/templates/scan/ip-table.html +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/templates/scan/overview.html +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/templates/scan/scan-error.html +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/templates/scan.html +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape/ui/templates/shutdown.html +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape.egg-info/dependency_links.txt +0 -0
- {lanscape-1.3.1a8/src → lanscape-1.3.2a6}/lanscape.egg-info/top_level.txt +0 -0
- {lanscape-1.3.1a8 → lanscape-1.3.2a6}/setup.cfg +0 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lanscape
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.2a6
|
|
4
4
|
Summary: A python based local network scanner
|
|
5
5
|
Author-email: Michael Dennis <michael@dipduo.com>
|
|
6
|
+
License-Expression: MIT
|
|
6
7
|
Project-URL: Homepage, https://github.com/mdennis281/py-lanscape
|
|
7
8
|
Project-URL: Issues, https://github.com/mdennis281/py-lanscape/issues
|
|
9
|
+
Keywords: network,scanner,lan,local,python
|
|
8
10
|
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
10
11
|
Classifier: Operating System :: OS Independent
|
|
11
12
|
Requires-Python: >=3.8
|
|
12
13
|
Description-Content-Type: text/markdown
|
|
@@ -17,7 +18,7 @@ Requires-Dist: requests<3.0,>=2.32
|
|
|
17
18
|
Requires-Dist: setuptools
|
|
18
19
|
Requires-Dist: scapy<3.0,>=2.3.2
|
|
19
20
|
Requires-Dist: tabulate==0.9.0
|
|
20
|
-
Requires-Dist:
|
|
21
|
+
Requires-Dist: pydantic
|
|
21
22
|
Dynamic: license-file
|
|
22
23
|
|
|
23
24
|
# LANscape
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Local network scanner
|
|
3
|
+
"""
|
|
1
4
|
from .libraries.subnet_scan import (
|
|
2
5
|
SubnetScanner,
|
|
3
6
|
ScanConfig,
|
|
@@ -6,4 +9,4 @@ from .libraries.subnet_scan import (
|
|
|
6
9
|
|
|
7
10
|
from .libraries.port_manager import PortManager
|
|
8
11
|
|
|
9
|
-
from .libraries import net_tools
|
|
12
|
+
from .libraries import net_tools
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
|
|
5
5
|
<script src="{{ url_for('static', filename='js/core.js') }}"></script>
|
|
6
6
|
|
|
7
|
-
{% if
|
|
7
|
+
{% if section is not defined %}
|
|
8
8
|
<script src="{{ url_for('static', filename='js/on-tab-close.js') }}"></script>
|
|
9
9
|
{% endif %}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<div id="header">
|
|
5
5
|
<!-- Header and Scan Submission Inline -->
|
|
6
6
|
<div class="d-flex justify-content-start align-items-center">
|
|
7
|
-
<a href="/" class="text-decoration-none">
|
|
7
|
+
<a href="/" class="text-decoration-none" aria-label="Go to homepage">
|
|
8
8
|
<h1 class="title">
|
|
9
9
|
<span>LAN</span>scape
|
|
10
10
|
</h1>
|
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
<div id="header">
|
|
5
5
|
<!-- Header and Scan Submission Inline -->
|
|
6
6
|
<div class="d-flex justify-content-between align-items-center flex-wrap">
|
|
7
|
-
<
|
|
8
|
-
<
|
|
9
|
-
|
|
7
|
+
<a href="/" class="text-decoration-none" aria-label="Go to homepage">
|
|
8
|
+
<h1 class="title">
|
|
9
|
+
<span>LAN</span>scape
|
|
10
|
+
</h1>
|
|
11
|
+
</a>
|
|
10
12
|
<!-- Form -->
|
|
11
13
|
<form id="scan-form" class="d-flex align-items-end">
|
|
12
14
|
<div class="form-group me-2">
|
|
@@ -52,7 +54,7 @@
|
|
|
52
54
|
<!-- ARP Error -->
|
|
53
55
|
<div id="arp-error" class="{{ 'div-hide' if is_arp_supported else '' }}">
|
|
54
56
|
<span>
|
|
55
|
-
Unable to
|
|
57
|
+
Unable to use ARP lookup. Device discovery is degraded.
|
|
56
58
|
<a target="_blank" href="https://github.com/mdennis281/LANscape/blob/main/support/arp-issues.md">Steps to fix</a>
|
|
57
59
|
</span>
|
|
58
60
|
</div>
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lanscape
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.2a6
|
|
4
4
|
Summary: A python based local network scanner
|
|
5
5
|
Author-email: Michael Dennis <michael@dipduo.com>
|
|
6
|
+
License-Expression: MIT
|
|
6
7
|
Project-URL: Homepage, https://github.com/mdennis281/py-lanscape
|
|
7
8
|
Project-URL: Issues, https://github.com/mdennis281/py-lanscape/issues
|
|
9
|
+
Keywords: network,scanner,lan,local,python
|
|
8
10
|
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
10
11
|
Classifier: Operating System :: OS Independent
|
|
11
12
|
Requires-Python: >=3.8
|
|
12
13
|
Description-Content-Type: text/markdown
|
|
@@ -17,7 +18,7 @@ Requires-Dist: requests<3.0,>=2.32
|
|
|
17
18
|
Requires-Dist: setuptools
|
|
18
19
|
Requires-Dist: scapy<3.0,>=2.3.2
|
|
19
20
|
Requires-Dist: tabulate==0.9.0
|
|
20
|
-
Requires-Dist:
|
|
21
|
+
Requires-Dist: pydantic
|
|
21
22
|
Dynamic: license-file
|
|
22
23
|
|
|
23
24
|
# LANscape
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
lanscape/__init__.py
|
|
6
|
+
lanscape/__main__.py
|
|
7
|
+
lanscape.egg-info/PKG-INFO
|
|
8
|
+
lanscape.egg-info/SOURCES.txt
|
|
9
|
+
lanscape.egg-info/dependency_links.txt
|
|
10
|
+
lanscape.egg-info/requires.txt
|
|
11
|
+
lanscape.egg-info/top_level.txt
|
|
12
|
+
lanscape/resources/mac_addresses/mac_db.json
|
|
13
|
+
lanscape/resources/ports/full.json
|
|
14
|
+
lanscape/resources/ports/large.json
|
|
15
|
+
lanscape/resources/ports/medium.json
|
|
16
|
+
lanscape/resources/ports/small.json
|
|
17
|
+
lanscape/resources/services/definitions.jsonc
|
|
18
|
+
lanscape/ui/static/lanscape.webmanifest
|
|
19
|
+
lanscape/ui/static/css/style.css
|
|
20
|
+
lanscape/ui/static/img/ico/android-chrome-192x192.png
|
|
21
|
+
lanscape/ui/static/img/ico/android-chrome-512x512.png
|
|
22
|
+
lanscape/ui/static/img/ico/apple-touch-icon.png
|
|
23
|
+
lanscape/ui/static/img/ico/favicon-16x16.png
|
|
24
|
+
lanscape/ui/static/img/ico/favicon-32x32.png
|
|
25
|
+
lanscape/ui/static/img/ico/favicon.ico
|
|
26
|
+
lanscape/ui/static/img/ico/site.webmanifest
|
|
27
|
+
lanscape/ui/static/js/core.js
|
|
28
|
+
lanscape/ui/static/js/layout-sizing.js
|
|
29
|
+
lanscape/ui/static/js/main.js
|
|
30
|
+
lanscape/ui/static/js/on-tab-close.js
|
|
31
|
+
lanscape/ui/static/js/quietReload.js
|
|
32
|
+
lanscape/ui/static/js/shutdown-server.js
|
|
33
|
+
lanscape/ui/static/js/subnet-info.js
|
|
34
|
+
lanscape/ui/static/js/subnet-selector.js
|
|
35
|
+
lanscape/ui/templates/base.html
|
|
36
|
+
lanscape/ui/templates/error.html
|
|
37
|
+
lanscape/ui/templates/info.html
|
|
38
|
+
lanscape/ui/templates/main.html
|
|
39
|
+
lanscape/ui/templates/scan.html
|
|
40
|
+
lanscape/ui/templates/shutdown.html
|
|
41
|
+
lanscape/ui/templates/core/head.html
|
|
42
|
+
lanscape/ui/templates/core/scripts.html
|
|
43
|
+
lanscape/ui/templates/scan/export.html
|
|
44
|
+
lanscape/ui/templates/scan/ip-table-row.html
|
|
45
|
+
lanscape/ui/templates/scan/ip-table.html
|
|
46
|
+
lanscape/ui/templates/scan/overview.html
|
|
47
|
+
lanscape/ui/templates/scan/scan-error.html
|
|
48
|
+
tests/test_api.py
|
|
49
|
+
tests/test_env.py
|
|
50
|
+
tests/test_library.py
|
|
51
|
+
tests/test_utils.py
|
|
@@ -1,26 +1,31 @@
|
|
|
1
|
-
[project]
|
|
2
|
-
name = "lanscape"
|
|
3
|
-
version = "1.3.
|
|
4
|
-
authors = [
|
|
5
|
-
{ name="Michael Dennis", email="michael@dipduo.com" },
|
|
6
|
-
]
|
|
7
|
-
description = "A python based local network scanner"
|
|
8
|
-
readme = "README.md"
|
|
9
|
-
requires-python = ">=3.8"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
[project]
|
|
2
|
+
name = "lanscape"
|
|
3
|
+
version = "1.3.2a6"
|
|
4
|
+
authors = [
|
|
5
|
+
{ name="Michael Dennis", email="michael@dipduo.com" },
|
|
6
|
+
]
|
|
7
|
+
description = "A python based local network scanner"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.8"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
keywords = ["network", "scanner", "lan", "local", "python"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Operating System :: OS Independent",
|
|
16
|
+
]
|
|
17
|
+
dependencies = [
|
|
18
|
+
"Flask>=3.0,<5.0",
|
|
19
|
+
"psutil>=6.0,<7.0",
|
|
20
|
+
"requests>=2.32,<3.0",
|
|
21
|
+
"setuptools",
|
|
22
|
+
"scapy>=2.3.2,<3.0",
|
|
23
|
+
"tabulate==0.9.0",
|
|
24
|
+
"pydantic"
|
|
25
|
+
]
|
|
26
|
+
[project.urls]
|
|
27
|
+
Homepage = "https://github.com/mdennis281/py-lanscape"
|
|
28
|
+
Issues = "https://github.com/mdennis281/py-lanscape/issues"
|
|
29
|
+
|
|
30
|
+
[tool.setuptools]
|
|
31
|
+
packages = ["lanscape"] # Explicitly list your packages
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import unittest
|
|
2
2
|
import json
|
|
3
|
-
from
|
|
4
|
-
from
|
|
3
|
+
from lanscape.ui.app import app
|
|
4
|
+
from lanscape.libraries.net_tools import get_network_subnet
|
|
5
5
|
from ._helpers import right_size_subnet
|
|
6
6
|
import time
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
class ApiTestCase(unittest.TestCase):
|
|
11
10
|
app = app.test_client()
|
|
12
11
|
|
|
@@ -21,10 +20,10 @@ class ApiTestCase(unittest.TestCase):
|
|
|
21
20
|
|
|
22
21
|
# Create a new port list
|
|
23
22
|
new_port_list = {'80': 'http', '443': 'https'}
|
|
24
|
-
response = self.app.post(
|
|
23
|
+
response = self.app.post(
|
|
24
|
+
'/api/port/list/test_port_list_lifecycle', json=new_port_list)
|
|
25
25
|
self.assertEqual(response.status_code, 200)
|
|
26
26
|
|
|
27
|
-
|
|
28
27
|
# Get the list of port lists again
|
|
29
28
|
response = self.app.get('/api/port/list')
|
|
30
29
|
self.assertEqual(response.status_code, 200)
|
|
@@ -40,7 +39,8 @@ class ApiTestCase(unittest.TestCase):
|
|
|
40
39
|
|
|
41
40
|
# Update the new port list
|
|
42
41
|
updated_port_list = {'22': 'ssh', '8080': 'http-alt'}
|
|
43
|
-
response = self.app.put(
|
|
42
|
+
response = self.app.put(
|
|
43
|
+
'/api/port/list/test_port_list_lifecycle', json=updated_port_list)
|
|
44
44
|
self.assertEqual(response.status_code, 200)
|
|
45
45
|
|
|
46
46
|
# Get the new port list again
|
|
@@ -61,11 +61,13 @@ class ApiTestCase(unittest.TestCase):
|
|
|
61
61
|
|
|
62
62
|
# Create a new port list
|
|
63
63
|
new_port_list = {'80': 'http', '443': 'https'}
|
|
64
|
-
response = self.app.post(
|
|
64
|
+
response = self.app.post(
|
|
65
|
+
'/api/port/list/test_port_list_scan', json=new_port_list)
|
|
65
66
|
self.assertEqual(response.status_code, 200)
|
|
66
67
|
|
|
67
68
|
# Create a new scan, wait for completion
|
|
68
|
-
new_scan = {'subnet': right_size_subnet(
|
|
69
|
+
new_scan = {'subnet': right_size_subnet(
|
|
70
|
+
get_network_subnet()), 'port_list': 'test_port_list_scan'}
|
|
69
71
|
response = self.app.post('/api/scan/async', json=new_scan)
|
|
70
72
|
self.assertEqual(response.status_code, 200)
|
|
71
73
|
scan_info = json.loads(response.data)
|
|
@@ -78,26 +80,14 @@ class ApiTestCase(unittest.TestCase):
|
|
|
78
80
|
self.assertEqual(response.status_code, 200)
|
|
79
81
|
scan_data = json.loads(response.data)
|
|
80
82
|
self.assertEqual(scan_data['errors'], [])
|
|
81
|
-
self.assertEqual(scan_data['stage'],'complete')
|
|
82
|
-
|
|
83
|
-
# Render UI
|
|
84
|
-
uris = [
|
|
85
|
-
'/info',
|
|
86
|
-
f'/?scan_id={scanid}',
|
|
87
|
-
f'/scan/{scanid}/overview',
|
|
88
|
-
f'/scan/{scanid}/table',
|
|
89
|
-
f'/export/{scanid}'
|
|
90
|
-
]
|
|
91
|
-
for uri in uris:
|
|
92
|
-
response = self.app.get(uri)
|
|
93
|
-
self.assertEqual(response.status_code,200)
|
|
83
|
+
self.assertEqual(scan_data['stage'], 'complete')
|
|
94
84
|
|
|
85
|
+
self._render_scan_ui(scanid)
|
|
95
86
|
|
|
96
87
|
# Delete the new port list
|
|
97
88
|
response = self.app.delete('/api/port/list/test_port_list_scan')
|
|
98
89
|
self.assertEqual(response.status_code, 200)
|
|
99
90
|
|
|
100
|
-
|
|
101
91
|
def test_subnet_ports(self):
|
|
102
92
|
"""
|
|
103
93
|
Test to ensure multi-subnet dectection is working
|
|
@@ -108,8 +98,8 @@ class ApiTestCase(unittest.TestCase):
|
|
|
108
98
|
|
|
109
99
|
subnets = json.loads(response.data)
|
|
110
100
|
self.assertIsNot(len(subnets), 0)
|
|
111
|
-
self.assertIsInstance(subnets[0],dict)
|
|
112
|
-
subnet:dict = subnets[0]
|
|
101
|
+
self.assertIsInstance(subnets[0], dict)
|
|
102
|
+
subnet: dict = subnets[0]
|
|
113
103
|
self.assertIsNotNone(subnet.get('address_cnt'))
|
|
114
104
|
|
|
115
105
|
def test_subnet_validation(self):
|
|
@@ -125,9 +115,9 @@ class ApiTestCase(unittest.TestCase):
|
|
|
125
115
|
'10.0.0.1/24, 192.168.1.1-100': 354,
|
|
126
116
|
'10.0.0.1/20': 4094,
|
|
127
117
|
'10.0.0.1/19': 8190,
|
|
128
|
-
'': -1,
|
|
129
|
-
'10.0.1/24': -1,
|
|
130
|
-
'10.0.0.1/2': -1,
|
|
118
|
+
'': -1, # blank
|
|
119
|
+
'10.0.1/24': -1, # invalid
|
|
120
|
+
'10.0.0.1/2': -1, # too big
|
|
131
121
|
'10.0.0.1/19, 192.168.1.1/20': 12284,
|
|
132
122
|
'10.0.0.1/17, 192.168.0.1/16': 98300,
|
|
133
123
|
'10.0.0.1/20, 192.168.0.1/20, 10.100.0.1/20': 12282,
|
|
@@ -139,12 +129,24 @@ class ApiTestCase(unittest.TestCase):
|
|
|
139
129
|
response = self.app.get(uri)
|
|
140
130
|
self.assertEqual(response.status_code, 200)
|
|
141
131
|
|
|
142
|
-
data:dict = json.loads(response.data)
|
|
143
|
-
self.assertEqual(data.get('count'),count)
|
|
132
|
+
data: dict = json.loads(response.data)
|
|
133
|
+
self.assertEqual(data.get('count'), count)
|
|
144
134
|
self.assertIsNotNone(data.get('msg'))
|
|
145
135
|
if count == -1:
|
|
146
136
|
self.assertFalse(data.get('valid'))
|
|
147
|
-
|
|
137
|
+
|
|
138
|
+
def _render_scan_ui(self, scanid):
|
|
139
|
+
uris = [
|
|
140
|
+
'/info',
|
|
141
|
+
f'/?scan_id={scanid}',
|
|
142
|
+
f'/scan/{scanid}/overview',
|
|
143
|
+
f'/scan/{scanid}/table',
|
|
144
|
+
f'/export/{scanid}'
|
|
145
|
+
]
|
|
146
|
+
for uri in uris:
|
|
147
|
+
response = self.app.get(uri)
|
|
148
|
+
self.assertEqual(response.status_code, 200)
|
|
149
|
+
|
|
148
150
|
def test_scan_api(self):
|
|
149
151
|
"""
|
|
150
152
|
Test the scan API endpoints
|
|
@@ -168,13 +170,16 @@ class ApiTestCase(unittest.TestCase):
|
|
|
168
170
|
response = self.app.get(f'/api/scan/{scan_id}/summary')
|
|
169
171
|
self.assertEqual(response.status_code, 200)
|
|
170
172
|
summary = json.loads(response.data)
|
|
171
|
-
self.assertTrue(summary['running']
|
|
173
|
+
self.assertTrue(summary['running']
|
|
174
|
+
or summary['stage'] == 'complete')
|
|
172
175
|
percent_complete = summary['percent_complete']
|
|
173
176
|
self.assertGreaterEqual(percent_complete, 0)
|
|
174
177
|
self.assertLessEqual(percent_complete, 100)
|
|
175
178
|
# Wait for a bit before checking again
|
|
179
|
+
|
|
180
|
+
self._render_scan_ui(scan_id)
|
|
176
181
|
time.sleep(2)
|
|
177
|
-
|
|
182
|
+
|
|
178
183
|
self.assertEqual(summary['running'], False)
|
|
179
184
|
self.assertEqual(summary['stage'], 'complete')
|
|
180
185
|
self.assertGreater(summary['runtime'], 0)
|
|
@@ -187,8 +192,5 @@ class ApiTestCase(unittest.TestCase):
|
|
|
187
192
|
self.assertGreater(devices_alive, 0)
|
|
188
193
|
|
|
189
194
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
195
|
if __name__ == '__main__':
|
|
194
|
-
unittest.main()
|
|
196
|
+
unittest.main()
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import unittest
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from
|
|
5
|
-
from
|
|
6
|
-
|
|
3
|
+
from lanscape.libraries.version_manager import lookup_latest_version
|
|
4
|
+
from lanscape.libraries.app_scope import ResourceManager, is_local_run
|
|
5
|
+
from lanscape.libraries.net_tools import is_arp_supported
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
class EnvTestCase(unittest.TestCase):
|
|
@@ -13,18 +12,16 @@ class EnvTestCase(unittest.TestCase):
|
|
|
13
12
|
|
|
14
13
|
def test_resource_manager(self):
|
|
15
14
|
ports = ResourceManager('ports')
|
|
16
|
-
self.assertGreater(len(ports.list()),0)
|
|
15
|
+
self.assertGreater(len(ports.list()), 0)
|
|
17
16
|
mac = ResourceManager('mac_addresses')
|
|
18
17
|
mac_list = mac.get('mac_db.json')
|
|
19
18
|
self.assertIsNotNone(mac_list)
|
|
20
|
-
|
|
19
|
+
|
|
21
20
|
def test_local_version(self):
|
|
22
21
|
self.assertTrue(is_local_run())
|
|
23
|
-
|
|
22
|
+
|
|
24
23
|
def test_arp_support(self):
|
|
25
24
|
arp_supported = is_arp_supported()
|
|
26
25
|
self.assertIn(arp_supported, [True, False],
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
f"ARP support should be either True or False, not {arp_supported}"
|
|
27
|
+
)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from lanscape.libraries.net_tools import smart_select_primary_subnet
|
|
3
|
+
from ._helpers import right_size_subnet
|
|
4
|
+
from lanscape.libraries.subnet_scan import ScanManager
|
|
5
|
+
from lanscape.libraries.scan_config import ScanConfig, PingConfig, ArpConfig, ScanType
|
|
6
|
+
|
|
7
|
+
sm = ScanManager()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class LibraryTestCase(unittest.TestCase):
|
|
11
|
+
def test_scan_config(self):
|
|
12
|
+
|
|
13
|
+
subnet_val = '192.168.1.1/24'
|
|
14
|
+
do_port_scan = False
|
|
15
|
+
ping_attempts = 3
|
|
16
|
+
arp_timeout = 2.0
|
|
17
|
+
|
|
18
|
+
cfg = ScanConfig(
|
|
19
|
+
subnet=subnet_val,
|
|
20
|
+
port_list='small'
|
|
21
|
+
)
|
|
22
|
+
self.assertEqual(len(cfg.parse_subnet()), 254)
|
|
23
|
+
|
|
24
|
+
cfg.task_scan_ports = do_port_scan
|
|
25
|
+
cfg.ping_config.attempts = ping_attempts
|
|
26
|
+
cfg.arp_config.timeout = arp_timeout
|
|
27
|
+
cfg.lookup_type = ScanType.PING
|
|
28
|
+
|
|
29
|
+
data = cfg.to_dict()
|
|
30
|
+
self.assertTrue(isinstance(data['ping_config'], dict))
|
|
31
|
+
self.assertTrue(isinstance(data['arp_config'], dict))
|
|
32
|
+
|
|
33
|
+
cfg2 = ScanConfig.from_dict(data)
|
|
34
|
+
|
|
35
|
+
# ensure the config was properly converted back
|
|
36
|
+
self.assertEqual(cfg2.subnet, subnet_val)
|
|
37
|
+
self.assertEqual(cfg2.port_list, 'small')
|
|
38
|
+
self.assertEqual(cfg2.task_scan_ports, do_port_scan)
|
|
39
|
+
self.assertEqual(cfg2.ping_config.attempts, ping_attempts)
|
|
40
|
+
self.assertEqual(cfg2.arp_config.timeout, arp_timeout)
|
|
41
|
+
self.assertEqual(cfg2.lookup_type, ScanType.PING)
|
|
42
|
+
|
|
43
|
+
def test_scan(self):
|
|
44
|
+
subnet = smart_select_primary_subnet()
|
|
45
|
+
self.assertIsNotNone(subnet)
|
|
46
|
+
cfg = ScanConfig(
|
|
47
|
+
subnet=right_size_subnet(subnet),
|
|
48
|
+
t_multiplier=1.0,
|
|
49
|
+
port_list='small'
|
|
50
|
+
)
|
|
51
|
+
scan = sm.new_scan(cfg)
|
|
52
|
+
self.assertTrue(scan.running)
|
|
53
|
+
sm.wait_until_complete(scan.uid)
|
|
54
|
+
|
|
55
|
+
self.assertFalse(scan.running)
|
|
56
|
+
|
|
57
|
+
# ensure there are not any remaining running threads
|
|
58
|
+
self.assertDictEqual(scan.job_stats.running, {})
|
|
59
|
+
|
|
60
|
+
cnt_with_hostname = 0
|
|
61
|
+
ips = []
|
|
62
|
+
macs = []
|
|
63
|
+
for d in scan.results.devices:
|
|
64
|
+
if d.hostname:
|
|
65
|
+
cnt_with_hostname += 1
|
|
66
|
+
# ensure there arent dupe mac addresses
|
|
67
|
+
|
|
68
|
+
if d.get_mac() in macs:
|
|
69
|
+
print(f"Warning: Duplicate MAC address found: {d.get_mac()}")
|
|
70
|
+
macs.append(d.get_mac())
|
|
71
|
+
|
|
72
|
+
# ensure there arent dupe ips
|
|
73
|
+
self.assertNotIn(d.ip, ips)
|
|
74
|
+
ips.append(d.ip)
|
|
75
|
+
|
|
76
|
+
# device must be alive to be in this list
|
|
77
|
+
self.assertTrue(d.alive)
|
|
78
|
+
|
|
79
|
+
# find at least one device
|
|
80
|
+
self.assertGreater(len(scan.results.devices), 0)
|
|
81
|
+
|
|
82
|
+
# ensure everything got scanned
|
|
83
|
+
self.assertEqual(scan.results.devices_scanned,
|
|
84
|
+
scan.results.devices_total)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from lanscape.libraries.ip_parser import parse_ip_input
|
|
3
|
+
from lanscape.libraries.errors import SubnetTooLargeError
|
|
4
|
+
import ipaddress
|
|
5
|
+
from lanscape.libraries import ip_parser
|
|
6
|
+
from lanscape.libraries.errors import SubnetTooLargeError
|
|
7
|
+
from lanscape.libraries.port_manager import PortManager
|
|
8
|
+
from lanscape.libraries.decorators import timeout_enforcer
|
|
9
|
+
import time
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class IPParserTests(unittest.TestCase):
|
|
13
|
+
def test_parse_cidr(self):
|
|
14
|
+
ips = parse_ip_input('192.168.0.0/30')
|
|
15
|
+
self.assertEqual([str(ip) for ip in ips], [
|
|
16
|
+
'192.168.0.1', '192.168.0.2'])
|
|
17
|
+
|
|
18
|
+
def test_parse_range(self):
|
|
19
|
+
ips = parse_ip_input('10.0.0.1-10.0.0.3')
|
|
20
|
+
self.assertEqual(len(ips), 3)
|
|
21
|
+
self.assertEqual(str(ips[0]), '10.0.0.1')
|
|
22
|
+
self.assertEqual(str(ips[-1]), '10.0.0.3')
|
|
23
|
+
|
|
24
|
+
def test_parse_shorthand_range(self):
|
|
25
|
+
ips = parse_ip_input('10.0.0.1-3')
|
|
26
|
+
self.assertEqual([str(ip) for ip in ips], [
|
|
27
|
+
'10.0.0.1', '10.0.0.2', '10.0.0.3'])
|
|
28
|
+
|
|
29
|
+
def test_parse_too_large_subnet(self):
|
|
30
|
+
with self.assertRaises(SubnetTooLargeError):
|
|
31
|
+
parse_ip_input('10.0.0.0/8')
|
|
32
|
+
|
|
33
|
+
def test_parse_ip_input_mixed(self):
|
|
34
|
+
ip_input = "10.0.0.1/30, 10.0.0.10-10.0.0.12, 10.0.0.20-22, 10.0.0.50"
|
|
35
|
+
result = ip_parser.parse_ip_input(ip_input)
|
|
36
|
+
expected = [
|
|
37
|
+
ipaddress.IPv4Address("10.0.0.1"),
|
|
38
|
+
ipaddress.IPv4Address("10.0.0.2"),
|
|
39
|
+
ipaddress.IPv4Address("10.0.0.10"),
|
|
40
|
+
ipaddress.IPv4Address("10.0.0.11"),
|
|
41
|
+
ipaddress.IPv4Address("10.0.0.12"),
|
|
42
|
+
ipaddress.IPv4Address("10.0.0.20"),
|
|
43
|
+
ipaddress.IPv4Address("10.0.0.21"),
|
|
44
|
+
ipaddress.IPv4Address("10.0.0.22"),
|
|
45
|
+
ipaddress.IPv4Address("10.0.0.50"),
|
|
46
|
+
]
|
|
47
|
+
self.assertEqual(result, expected)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class PortManagerValidateTests(unittest.TestCase):
|
|
51
|
+
def setUp(self):
|
|
52
|
+
# Avoid running __init__ which touches the filesystem
|
|
53
|
+
self.pm = PortManager.__new__(PortManager)
|
|
54
|
+
|
|
55
|
+
def test_validate_port_data_valid(self):
|
|
56
|
+
valid = {"80": "http", "443": "https"}
|
|
57
|
+
self.assertTrue(PortManager.validate_port_data(self.pm, valid))
|
|
58
|
+
|
|
59
|
+
def test_validate_port_data_invalid(self):
|
|
60
|
+
invalid_cases = [
|
|
61
|
+
{"-1": "neg"}, # negative port
|
|
62
|
+
{"70000": "too_high"}, # port out of range
|
|
63
|
+
{"abc": "not_int"}, # non-integer port
|
|
64
|
+
{"80": 123}, # service not a string
|
|
65
|
+
]
|
|
66
|
+
for case in invalid_cases:
|
|
67
|
+
with self.subTest(case=case):
|
|
68
|
+
self.assertFalse(PortManager.validate_port_data(self.pm, case))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class DecoratorTimeoutTests(unittest.TestCase):
|
|
72
|
+
def test_timeout_enforcer(self):
|
|
73
|
+
@timeout_enforcer(0.1, raise_on_timeout=False)
|
|
74
|
+
def slow_return():
|
|
75
|
+
time.sleep(0.2)
|
|
76
|
+
return "done"
|
|
77
|
+
|
|
78
|
+
self.assertIsNone(slow_return())
|
|
79
|
+
|
|
80
|
+
@timeout_enforcer(0.1, raise_on_timeout=True)
|
|
81
|
+
def slow_raise():
|
|
82
|
+
time.sleep(0.2)
|
|
83
|
+
return "done"
|
|
84
|
+
|
|
85
|
+
with self.assertRaises(TimeoutError):
|
|
86
|
+
slow_raise()
|
lanscape-1.3.1a8/MANIFEST.in
DELETED