cloud-auditor 0.1.0__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.
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: cloud_auditor
3
+ Version: 0.1.0
4
+ Summary: Layer 7 Cloud-Aware Web Security Auditor
5
+ Author: Hadi
6
+ Project-URL: Homepage, https://github.com/hadezedan34/cloud_auditor
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: requests>=2.28.0
@@ -0,0 +1,3 @@
1
+ from .scanner import CloudAuditor
2
+
3
+ __all__ = ["CloudAuditor"]
@@ -0,0 +1,118 @@
1
+ import socket
2
+ import ssl
3
+ import requests
4
+ from datetime import datetime, timezone
5
+ from concurrent.futures import ThreadPoolExecutor, as_completed
6
+
7
+ COMMON_PORTS = {
8
+ 80: ("HTTP", "http"),
9
+ 443: ("HTTPS", "https"),
10
+ 8080: ("HTTP-Proxy", "http"),
11
+ 8443: ("HTTPS-Alt", "https"),
12
+ 22: ("SSH", None),
13
+ 21: ("FTP", None),
14
+ 3306: ("MySQL", None)
15
+ }
16
+
17
+ SECURITY_HEADERS = [
18
+ "Strict-Transport-Security",
19
+ "Content-Security-Policy",
20
+ "X-Frame-Options",
21
+ "X-Content-Type-Options",
22
+ "Referrer-Policy",
23
+ "Permissions-Policy"
24
+ ]
25
+
26
+ class CloudAuditor:
27
+ """Core scanning class for cloud-aware web application security audits."""
28
+
29
+ def __init__(self, target_host: str, max_workers: int = 10):
30
+ self.target_host = target_host.strip().replace("http://", "").replace("https://", "").split('/')[0]
31
+ self.max_workers = max_workers
32
+ self.target_ip = None
33
+ self.open_ports = []
34
+ self.active_base_url = None
35
+
36
+ def resolve(self) -> str:
37
+ """Resolves target IP and performs warm-up."""
38
+ self.target_ip = socket.gethostbyname(self.target_host)
39
+ try:
40
+ requests.get(f"https://{self.target_host}", timeout=5)
41
+ except Exception:
42
+ pass
43
+ return self.target_ip
44
+
45
+ def _probe_port(self, port: int, service_info: tuple):
46
+ service_name, scheme = service_info
47
+ if scheme:
48
+ url = f"{scheme}://{self.target_host}:{port}" if port not in [80, 443] else f"{scheme}://{self.target_host}"
49
+ try:
50
+ res = requests.head(url, timeout=4, headers={"User-Agent": "CloudAuditor/1.0"})
51
+ return (port, service_name, True, f"HTTP {res.status_code}")
52
+ except requests.RequestException:
53
+ pass
54
+
55
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
56
+ s.settimeout(2.0)
57
+ try:
58
+ if s.connect_ex((self.target_ip, port)) == 0:
59
+ return (port, service_name, True, "TCP Open")
60
+ except Exception:
61
+ pass
62
+ finally:
63
+ s.close()
64
+
65
+ return (port, service_name, False, "Closed")
66
+
67
+ def scan_ports(self) -> dict:
68
+ """Scans standard ports using Layer 7 and Layer 4 probes."""
69
+ if not self.target_ip:
70
+ self.resolve()
71
+
72
+ results = {}
73
+ with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
74
+ futures = [executor.submit(self._probe_port, p, s) for p, s in COMMON_PORTS.items()]
75
+ for future in as_completed(futures):
76
+ port, service, is_open, status = future.result()
77
+ if is_open:
78
+ results[port] = {"service": service, "status": status}
79
+ self.open_ports.append(port)
80
+
81
+ if 443 in results:
82
+ self.active_base_url = f"https://{self.target_host}"
83
+ elif 80 in results:
84
+ self.active_base_url = f"http://{self.target_host}"
85
+
86
+ return results
87
+
88
+ def audit_headers(self) -> dict:
89
+ """Evaluates HTTP security header coverage."""
90
+ if not self.active_base_url:
91
+ self.scan_ports()
92
+ if not self.active_base_url:
93
+ return {"score": 0.0, "details": {}}
94
+
95
+ try:
96
+ res = requests.get(self.active_base_url, timeout=5)
97
+ found = [h for h in SECURITY_HEADERS if h in res.headers]
98
+ score = (len(found) / len(SECURITY_HEADERS)) * 100
99
+ return {
100
+ "score": score,
101
+ "present": found,
102
+ "missing": [h for h in SECURITY_HEADERS if h not in found]
103
+ }
104
+ except Exception as e:
105
+ return {"error": str(e)}
106
+
107
+ def run_full_audit(self) -> dict:
108
+ """Runs complete audit cycle and returns dictionary output."""
109
+ ip = self.resolve()
110
+ ports = self.scan_ports()
111
+ headers = self.audit_headers()
112
+ return {
113
+ "target": self.target_host,
114
+ "ip": ip,
115
+ "ports": ports,
116
+ "headers": headers,
117
+ "timestamp": datetime.now(timezone.utc).isoformat()
118
+ }
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.4
2
+ Name: cloud_auditor
3
+ Version: 0.1.0
4
+ Summary: Layer 7 Cloud-Aware Web Security Auditor
5
+ Author: Hadi
6
+ Project-URL: Homepage, https://github.com/hadezedan34/cloud_auditor
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: requests>=2.28.0
@@ -0,0 +1,8 @@
1
+ pyproject.toml
2
+ cloud_auditor/__init__.py
3
+ cloud_auditor/scanner.py
4
+ cloud_auditor.egg-info/PKG-INFO
5
+ cloud_auditor.egg-info/SOURCES.txt
6
+ cloud_auditor.egg-info/dependency_links.txt
7
+ cloud_auditor.egg-info/requires.txt
8
+ cloud_auditor.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ requests>=2.28.0
@@ -0,0 +1 @@
1
+ cloud_auditor
@@ -0,0 +1,17 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "cloud_auditor" #'
7
+ version = "0.1.0"
8
+ description = "Layer 7 Cloud-Aware Web Security Auditor"
9
+ readme = "README.md"
10
+ authors = [{ name = "Hadi" }]
11
+ requires-python = ">=3.8"
12
+ dependencies = [
13
+ "requests>=2.28.0"
14
+ ]
15
+
16
+ [project.urls]
17
+ "Homepage" = "https://github.com/hadezedan34/cloud_auditor"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+