devaudit-cli 0.3.0__py3-none-any.whl
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.
- dev_audit/__init__.py +0 -0
- dev_audit/__main__.py +4 -0
- dev_audit/audit.py +51 -0
- dev_audit/cli.py +110 -0
- dev_audit/collectors/__init__.py +0 -0
- dev_audit/collectors/devtools.py +113 -0
- dev_audit/collectors/network.py +172 -0
- dev_audit/collectors/resources.py +154 -0
- dev_audit/collectors/system.py +72 -0
- dev_audit/command.py +51 -0
- dev_audit/output.py +273 -0
- dev_audit/status.py +30 -0
- devaudit_cli-0.3.0.dist-info/METADATA +347 -0
- devaudit_cli-0.3.0.dist-info/RECORD +18 -0
- devaudit_cli-0.3.0.dist-info/WHEEL +5 -0
- devaudit_cli-0.3.0.dist-info/entry_points.txt +2 -0
- devaudit_cli-0.3.0.dist-info/licenses/LICENSE +21 -0
- devaudit_cli-0.3.0.dist-info/top_level.txt +1 -0
dev_audit/command.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def command_exists(command: str) -> bool:
|
|
8
|
+
return shutil.which(command) is not None
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def run_command(
|
|
12
|
+
command: list[str],
|
|
13
|
+
timeout: int = 5,
|
|
14
|
+
) -> dict:
|
|
15
|
+
try:
|
|
16
|
+
result = subprocess.run(
|
|
17
|
+
command,
|
|
18
|
+
capture_output=True,
|
|
19
|
+
text=True,
|
|
20
|
+
timeout=timeout,
|
|
21
|
+
check=False,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
"ok": result.returncode == 0,
|
|
26
|
+
"command": " ".join(command),
|
|
27
|
+
"returncode": result.returncode,
|
|
28
|
+
"stdout": result.stdout.strip(),
|
|
29
|
+
"stderr": result.stderr.strip(),
|
|
30
|
+
"error": None,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
except FileNotFoundError:
|
|
34
|
+
return {
|
|
35
|
+
"ok": False,
|
|
36
|
+
"command": " ".join(command),
|
|
37
|
+
"returncode": None,
|
|
38
|
+
"stdout": "",
|
|
39
|
+
"stderr": "",
|
|
40
|
+
"error": f"Command not found: {command[0]}",
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
except subprocess.TimeoutExpired:
|
|
44
|
+
return {
|
|
45
|
+
"ok": False,
|
|
46
|
+
"command": " ".join(command),
|
|
47
|
+
"returncode": None,
|
|
48
|
+
"stdout": "",
|
|
49
|
+
"stderr": "",
|
|
50
|
+
"error": f"Command timed out after {timeout}s",
|
|
51
|
+
}
|
dev_audit/output.py
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def format_duration(seconds: float | None) -> str:
|
|
7
|
+
if seconds is None:
|
|
8
|
+
return "unknown"
|
|
9
|
+
|
|
10
|
+
total_seconds = int(seconds)
|
|
11
|
+
days, remainder = divmod(total_seconds, 86400)
|
|
12
|
+
hours, remainder = divmod(remainder, 3600)
|
|
13
|
+
minutes, seconds = divmod(remainder, 60)
|
|
14
|
+
|
|
15
|
+
parts = []
|
|
16
|
+
|
|
17
|
+
if days:
|
|
18
|
+
parts.append(f"{days}d")
|
|
19
|
+
if hours:
|
|
20
|
+
parts.append(f"{hours}h")
|
|
21
|
+
if minutes:
|
|
22
|
+
parts.append(f"{minutes}m")
|
|
23
|
+
if seconds or not parts:
|
|
24
|
+
parts.append(f"{seconds}s")
|
|
25
|
+
|
|
26
|
+
return " ".join(parts)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def print_json(result: dict[str, object]) -> None:
|
|
30
|
+
print(json.dumps(result, indent=2, sort_keys=True))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def print_system(result: dict[str, object], verbose: bool = False) -> None:
|
|
34
|
+
data = result["data"]
|
|
35
|
+
|
|
36
|
+
print("System Information")
|
|
37
|
+
print("────────────────────────")
|
|
38
|
+
print(f"Hostname : {data['hostname']}")
|
|
39
|
+
print(f"OS : {data['os_name']} {data['os_version']}")
|
|
40
|
+
print(f"Kernel : {data['kernel']}")
|
|
41
|
+
print(f"Architecture : {data['architecture']}")
|
|
42
|
+
print(f"User : {data['user']}")
|
|
43
|
+
print(f"Shell : {data['shell']}")
|
|
44
|
+
print(f"Uptime : {format_duration(data['uptime_seconds'])}")
|
|
45
|
+
|
|
46
|
+
warnings = result.get("warnings", [])
|
|
47
|
+
|
|
48
|
+
if warnings:
|
|
49
|
+
print()
|
|
50
|
+
print("Warnings")
|
|
51
|
+
print("────────")
|
|
52
|
+
for warning in warnings:
|
|
53
|
+
print(f"⚠ {warning}")
|
|
54
|
+
|
|
55
|
+
if verbose:
|
|
56
|
+
print()
|
|
57
|
+
print("Raw Result")
|
|
58
|
+
print("──────────")
|
|
59
|
+
print_json(result)
|
|
60
|
+
|
|
61
|
+
def print_resources(result: dict[str, object], verbose: bool = False) -> None:
|
|
62
|
+
data = result["data"]
|
|
63
|
+
|
|
64
|
+
print("Resource Usage")
|
|
65
|
+
print("────────────────────────")
|
|
66
|
+
print(f"CPU Cores : {data['cpu_count']}")
|
|
67
|
+
|
|
68
|
+
load_average = data["load_average"]
|
|
69
|
+
if load_average:
|
|
70
|
+
print(
|
|
71
|
+
"Load Average : "
|
|
72
|
+
f"{load_average['1_min']} "
|
|
73
|
+
f"{load_average['5_min']} "
|
|
74
|
+
f"{load_average['15_min']}"
|
|
75
|
+
)
|
|
76
|
+
else:
|
|
77
|
+
print("Load Average : unknown")
|
|
78
|
+
|
|
79
|
+
memory = data["memory"]
|
|
80
|
+
print()
|
|
81
|
+
print("Memory")
|
|
82
|
+
print("──────")
|
|
83
|
+
print(f"Total : {memory['total_gib']} GiB")
|
|
84
|
+
print(f"Used : {memory['used_gib']} GiB")
|
|
85
|
+
print(f"Available : {memory['available_gib']} GiB")
|
|
86
|
+
print(f"Used Percent : {memory['used_percent']}%")
|
|
87
|
+
|
|
88
|
+
swap = data["swap"]
|
|
89
|
+
print()
|
|
90
|
+
print("Swap")
|
|
91
|
+
print("────")
|
|
92
|
+
print(f"Total : {swap['total_gib']} GiB")
|
|
93
|
+
print(f"Used : {swap['used_gib']} GiB")
|
|
94
|
+
print(f"Free : {swap['free_gib']} GiB")
|
|
95
|
+
print(f"Used Percent : {swap['used_percent']}%")
|
|
96
|
+
|
|
97
|
+
root_disk = data["root_disk"]
|
|
98
|
+
print()
|
|
99
|
+
print("Root Disk")
|
|
100
|
+
print("─────────")
|
|
101
|
+
print(f"Total : {root_disk['total_gib']} GiB")
|
|
102
|
+
print(f"Used : {root_disk['used_gib']} GiB")
|
|
103
|
+
print(f"Free : {root_disk['free_gib']} GiB")
|
|
104
|
+
print(f"Used Percent : {root_disk['used_percent']}%")
|
|
105
|
+
|
|
106
|
+
warnings = result.get("warnings", [])
|
|
107
|
+
|
|
108
|
+
if warnings:
|
|
109
|
+
print()
|
|
110
|
+
print("Warnings")
|
|
111
|
+
print("────────")
|
|
112
|
+
for warning in warnings:
|
|
113
|
+
print(f"⚠ {warning}")
|
|
114
|
+
|
|
115
|
+
if verbose:
|
|
116
|
+
print()
|
|
117
|
+
print("Mounts")
|
|
118
|
+
print("──────")
|
|
119
|
+
for mount in data["mounts"]:
|
|
120
|
+
print(
|
|
121
|
+
f"{mount['mount_point']} "
|
|
122
|
+
f"({mount['filesystem']}) "
|
|
123
|
+
f"← {mount['device']}"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
print()
|
|
127
|
+
print("Raw Result")
|
|
128
|
+
print("──────────")
|
|
129
|
+
print_json(result)
|
|
130
|
+
|
|
131
|
+
def print_network(result: dict[str, object], verbose: bool = False) -> None:
|
|
132
|
+
data = result["data"]
|
|
133
|
+
|
|
134
|
+
print("Network Information")
|
|
135
|
+
print("────────────────────────")
|
|
136
|
+
|
|
137
|
+
print("Interfaces")
|
|
138
|
+
print("──────────")
|
|
139
|
+
|
|
140
|
+
interfaces = data["interfaces"]
|
|
141
|
+
|
|
142
|
+
if interfaces:
|
|
143
|
+
for interface in interfaces:
|
|
144
|
+
print(
|
|
145
|
+
f"{interface['name']:<20} "
|
|
146
|
+
f"{interface['ipv4'] or 'No IPv4'}"
|
|
147
|
+
)
|
|
148
|
+
else:
|
|
149
|
+
print("No interfaces found")
|
|
150
|
+
|
|
151
|
+
print()
|
|
152
|
+
|
|
153
|
+
print("Default Route")
|
|
154
|
+
print("─────────────")
|
|
155
|
+
|
|
156
|
+
route = data["default_route"]
|
|
157
|
+
|
|
158
|
+
if route:
|
|
159
|
+
print(f"Gateway : {route['gateway']}")
|
|
160
|
+
print(f"Interface : {route['interface']}")
|
|
161
|
+
else:
|
|
162
|
+
print("No default route found")
|
|
163
|
+
|
|
164
|
+
print()
|
|
165
|
+
|
|
166
|
+
print("DNS Servers")
|
|
167
|
+
print("───────────")
|
|
168
|
+
|
|
169
|
+
dns_servers = data["dns_servers"]
|
|
170
|
+
|
|
171
|
+
if dns_servers:
|
|
172
|
+
for server in dns_servers:
|
|
173
|
+
print(f"- {server}")
|
|
174
|
+
else:
|
|
175
|
+
print("No DNS servers found")
|
|
176
|
+
|
|
177
|
+
print()
|
|
178
|
+
|
|
179
|
+
print("Listening Ports")
|
|
180
|
+
print("───────────────")
|
|
181
|
+
|
|
182
|
+
ports = data["listening_ports"]
|
|
183
|
+
|
|
184
|
+
if ports:
|
|
185
|
+
for port in ports[:10]:
|
|
186
|
+
print(
|
|
187
|
+
f"{port['protocol'].upper():<5} "
|
|
188
|
+
f"{port['local_address']}"
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
if len(ports) > 10:
|
|
192
|
+
print(
|
|
193
|
+
f"... {len(ports) - 10} more ports hidden. "
|
|
194
|
+
f"Use --verbose to see all."
|
|
195
|
+
)
|
|
196
|
+
else:
|
|
197
|
+
print("No listening ports found")
|
|
198
|
+
|
|
199
|
+
warnings = result.get("warnings", [])
|
|
200
|
+
|
|
201
|
+
if warnings:
|
|
202
|
+
print()
|
|
203
|
+
print("Warnings")
|
|
204
|
+
print("────────")
|
|
205
|
+
|
|
206
|
+
for warning in warnings:
|
|
207
|
+
print(f"⚠ {warning}")
|
|
208
|
+
|
|
209
|
+
if verbose:
|
|
210
|
+
print()
|
|
211
|
+
|
|
212
|
+
print("All Listening Ports")
|
|
213
|
+
print("──────────────────")
|
|
214
|
+
|
|
215
|
+
for port in ports:
|
|
216
|
+
print(
|
|
217
|
+
f"{port['protocol'].upper():<5} "
|
|
218
|
+
f"{port['local_address']}"
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
print()
|
|
222
|
+
|
|
223
|
+
print("Raw Result")
|
|
224
|
+
print("──────────")
|
|
225
|
+
|
|
226
|
+
print_json(result)
|
|
227
|
+
|
|
228
|
+
def print_devtools(result: dict[str, object], verbose: bool = False) -> None:
|
|
229
|
+
tools = result["data"]["tools"]
|
|
230
|
+
|
|
231
|
+
print("Developer Tools")
|
|
232
|
+
print("────────────────────────")
|
|
233
|
+
|
|
234
|
+
for tool in tools:
|
|
235
|
+
print()
|
|
236
|
+
print(tool["name"])
|
|
237
|
+
|
|
238
|
+
if tool["installed"]:
|
|
239
|
+
print("✓ Installed")
|
|
240
|
+
|
|
241
|
+
if tool["version"]:
|
|
242
|
+
print(f"Version : {tool['version']}")
|
|
243
|
+
|
|
244
|
+
if verbose and tool["path"]:
|
|
245
|
+
print(f"Path : {tool['path']}")
|
|
246
|
+
|
|
247
|
+
else:
|
|
248
|
+
print("✗ Not Installed")
|
|
249
|
+
|
|
250
|
+
warnings = result.get("warnings", [])
|
|
251
|
+
|
|
252
|
+
if warnings:
|
|
253
|
+
print()
|
|
254
|
+
print("Warnings")
|
|
255
|
+
print("────────")
|
|
256
|
+
|
|
257
|
+
for warning in warnings:
|
|
258
|
+
print(f"⚠ {warning}")
|
|
259
|
+
|
|
260
|
+
def print_findings(findings: list[str]) -> None:
|
|
261
|
+
if not findings:
|
|
262
|
+
print()
|
|
263
|
+
print("Audit Findings")
|
|
264
|
+
print("──────────────")
|
|
265
|
+
print("No findings detected.")
|
|
266
|
+
return
|
|
267
|
+
|
|
268
|
+
print()
|
|
269
|
+
print("Audit Findings")
|
|
270
|
+
print("──────────────")
|
|
271
|
+
|
|
272
|
+
for finding in findings:
|
|
273
|
+
print(f"⚠ {finding}")
|
dev_audit/status.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
EXIT_OK = 0
|
|
5
|
+
EXIT_FINDINGS = 1
|
|
6
|
+
EXIT_COLLECTOR_FAILURE = 2
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def has_collector_failure(results: dict[str, object]) -> bool:
|
|
10
|
+
for section_result in results.values():
|
|
11
|
+
if not isinstance(section_result, dict):
|
|
12
|
+
continue
|
|
13
|
+
|
|
14
|
+
if section_result.get("success") is False:
|
|
15
|
+
return True
|
|
16
|
+
|
|
17
|
+
return False
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def determine_exit_code(
|
|
21
|
+
results: dict[str, object],
|
|
22
|
+
findings: list[str],
|
|
23
|
+
) -> int:
|
|
24
|
+
if has_collector_failure(results):
|
|
25
|
+
return EXIT_COLLECTOR_FAILURE
|
|
26
|
+
|
|
27
|
+
if findings:
|
|
28
|
+
return EXIT_FINDINGS
|
|
29
|
+
|
|
30
|
+
return EXIT_OK
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: devaudit-cli
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Linux system inspection and developer environment audit tool
|
|
5
|
+
Author-email: Brenda Bonareri <bonarerijb24@gmail.com>
|
|
6
|
+
Keywords: linux,audit,cli,diagnostics,system-monitoring
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
|
|
21
|
+
# dev-audit
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
|
|
25
|
+

|
|
26
|
+

|
|
27
|
+

|
|
28
|
+

|
|
29
|
+
|
|
30
|
+
## Project Status
|
|
31
|
+
|
|
32
|
+
**Current Release:** v0.3.0
|
|
33
|
+
|
|
34
|
+
### Features
|
|
35
|
+
|
|
36
|
+
* Linux system inspection
|
|
37
|
+
* Resource monitoring
|
|
38
|
+
* Network auditing
|
|
39
|
+
* Developer tool validation
|
|
40
|
+
* Audit findings engine
|
|
41
|
+
* JSON output support
|
|
42
|
+
* Verbose output support
|
|
43
|
+
* Exit code support for automation
|
|
44
|
+
* GitHub Actions CI/CD
|
|
45
|
+
|
|
46
|
+
### Quality Metrics
|
|
47
|
+
|
|
48
|
+
* 44 passing tests
|
|
49
|
+
* 50% code coverage
|
|
50
|
+
* Automated CI validation
|
|
51
|
+
* Semantic versioning
|
|
52
|
+
* Tagged releases
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
A Linux system inspection and diagnostic CLI built for Ubuntu environments.
|
|
56
|
+
|
|
57
|
+
`dev-audit` collects system information, resource metrics, network configuration, and developer environment details, then evaluates the results against audit rules to identify potential issues.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Features
|
|
62
|
+
|
|
63
|
+
### System Audit
|
|
64
|
+
|
|
65
|
+
* Operating system information
|
|
66
|
+
* Kernel version
|
|
67
|
+
* Hostname
|
|
68
|
+
* Architecture
|
|
69
|
+
* User and shell
|
|
70
|
+
* System uptime
|
|
71
|
+
|
|
72
|
+
### Resource Audit
|
|
73
|
+
|
|
74
|
+
* CPU core count
|
|
75
|
+
* Load averages
|
|
76
|
+
* Memory utilization
|
|
77
|
+
* Swap utilization
|
|
78
|
+
* Root filesystem usage
|
|
79
|
+
|
|
80
|
+
### Network Audit
|
|
81
|
+
|
|
82
|
+
* Network interfaces
|
|
83
|
+
* Default route
|
|
84
|
+
* DNS configuration
|
|
85
|
+
* Listening TCP and UDP ports
|
|
86
|
+
|
|
87
|
+
### Developer Environment Audit
|
|
88
|
+
|
|
89
|
+
* Python
|
|
90
|
+
* pip
|
|
91
|
+
* Git
|
|
92
|
+
* Docker
|
|
93
|
+
* Docker Compose
|
|
94
|
+
* Node.js
|
|
95
|
+
* npm
|
|
96
|
+
|
|
97
|
+
### Audit Engine
|
|
98
|
+
|
|
99
|
+
Detects:
|
|
100
|
+
|
|
101
|
+
* Exposed SSH services
|
|
102
|
+
* HTTP services listening on all interfaces
|
|
103
|
+
* Inconsistent development tool installations
|
|
104
|
+
* WSL-specific tool resolution issues
|
|
105
|
+
|
|
106
|
+
### Output Modes
|
|
107
|
+
|
|
108
|
+
* Human-readable terminal output
|
|
109
|
+
* JSON output
|
|
110
|
+
* Verbose diagnostics
|
|
111
|
+
|
|
112
|
+
### Exit Codes
|
|
113
|
+
|
|
114
|
+
| Exit Code | Meaning |
|
|
115
|
+
| --------- | ----------------- |
|
|
116
|
+
| 0 | Healthy audit |
|
|
117
|
+
| 1 | Findings detected |
|
|
118
|
+
| 2 | Collector failure |
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Architecture
|
|
123
|
+
|
|
124
|
+
dev-audit follows a modular collector-based architecture.
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
CLI
|
|
128
|
+
│
|
|
129
|
+
├── System Collector
|
|
130
|
+
│ ├── OS Information
|
|
131
|
+
│ ├── Kernel Information
|
|
132
|
+
│ └── Uptime
|
|
133
|
+
│
|
|
134
|
+
├── Resource Collector
|
|
135
|
+
│ ├── CPU Usage
|
|
136
|
+
│ ├── Memory Usage
|
|
137
|
+
│ ├── Swap Usage
|
|
138
|
+
│ └── Disk Usage
|
|
139
|
+
│
|
|
140
|
+
├── Network Collector
|
|
141
|
+
│ ├── Interfaces
|
|
142
|
+
│ ├── DNS Servers
|
|
143
|
+
│ ├── Default Route
|
|
144
|
+
│ └── Listening Ports
|
|
145
|
+
│
|
|
146
|
+
├── DevTools Collector
|
|
147
|
+
│ ├── Python
|
|
148
|
+
│ ├── pip
|
|
149
|
+
│ ├── Git
|
|
150
|
+
│ ├── Docker
|
|
151
|
+
│ ├── Docker Compose
|
|
152
|
+
│ ├── Node.js
|
|
153
|
+
│ └── npm
|
|
154
|
+
│
|
|
155
|
+
└── Audit Engine
|
|
156
|
+
├── Resource Checks
|
|
157
|
+
├── Network Checks
|
|
158
|
+
└── Environment Checks
|
|
159
|
+
|
|
160
|
+
Output Layer
|
|
161
|
+
├── Human Readable Output
|
|
162
|
+
├── JSON Output
|
|
163
|
+
└── Exit Codes
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Design Goals
|
|
167
|
+
|
|
168
|
+
* Modular collector architecture
|
|
169
|
+
* Linux-first implementation
|
|
170
|
+
* Machine-readable JSON output
|
|
171
|
+
* Human-readable terminal output
|
|
172
|
+
* CI/CD validated
|
|
173
|
+
* Test-driven development
|
|
174
|
+
* Suitable for automation and scripting
|
|
175
|
+
|
|
176
|
+
## Example Output
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
$ dev-audit
|
|
180
|
+
|
|
181
|
+
System Information
|
|
182
|
+
────────────────────────
|
|
183
|
+
Hostname : ubuntu-server
|
|
184
|
+
OS : Ubuntu 24.04 LTS
|
|
185
|
+
Kernel : 6.8.0
|
|
186
|
+
Architecture : x86_64
|
|
187
|
+
User : ubuntu
|
|
188
|
+
|
|
189
|
+
Resource Usage
|
|
190
|
+
────────────────────────
|
|
191
|
+
CPU Cores : 8
|
|
192
|
+
Load Average : 0.10 0.12 0.08
|
|
193
|
+
|
|
194
|
+
Memory
|
|
195
|
+
──────
|
|
196
|
+
Total : 16.0 GiB
|
|
197
|
+
Used : 4.2 GiB
|
|
198
|
+
Available : 11.8 GiB
|
|
199
|
+
|
|
200
|
+
Audit Findings
|
|
201
|
+
──────────────
|
|
202
|
+
⚠ SSH is listening on all interfaces.
|
|
203
|
+
⚠ HTTP service exposed on all IPv4 interfaces.
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### JSON Output
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
$ dev-audit --json
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
```json
|
|
213
|
+
{
|
|
214
|
+
"system": {
|
|
215
|
+
"hostname": "ubuntu-server",
|
|
216
|
+
"kernel": "6.8.0"
|
|
217
|
+
},
|
|
218
|
+
"findings": [
|
|
219
|
+
"SSH is listening on all interfaces."
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Use Cases
|
|
225
|
+
|
|
226
|
+
`dev-audit` can be used to:
|
|
227
|
+
|
|
228
|
+
* Quickly inspect Linux development environments
|
|
229
|
+
* Validate workstation setup before software development
|
|
230
|
+
* Audit servers for exposed services and configuration issues
|
|
231
|
+
* Generate machine-readable JSON reports for automation
|
|
232
|
+
* Troubleshoot networking and developer tool installations
|
|
233
|
+
* Perform lightweight health checks on Ubuntu systems
|
|
234
|
+
|
|
235
|
+
## Installation
|
|
236
|
+
|
|
237
|
+
### Clone Repository
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
git clone https://github.com/Bonbonjb/dev-audit.git
|
|
241
|
+
cd dev-audit
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Create Virtual Environment
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
python3 -m venv .venv
|
|
248
|
+
source .venv/bin/activate
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Install Package
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
pip install -e .
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Usage
|
|
260
|
+
|
|
261
|
+
### Full Audit
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
dev-audit
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Run Individual Sections
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
dev-audit system
|
|
271
|
+
dev-audit resources
|
|
272
|
+
dev-audit network
|
|
273
|
+
dev-audit devtools
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### JSON Output
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
dev-audit --json
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Verbose Output
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
dev-audit --verbose
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Example Audit Findings
|
|
291
|
+
|
|
292
|
+
```text
|
|
293
|
+
⚠ SSH is listening on all interfaces.
|
|
294
|
+
⚠ HTTP service exposed on all IPv4 interfaces.
|
|
295
|
+
⚠ npm detected but Node.js executable not found.
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## Running Tests
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
pytest
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Current test suite:
|
|
307
|
+
|
|
308
|
+
```text
|
|
309
|
+
44 passing tests
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Project Structure
|
|
315
|
+
|
|
316
|
+
```text
|
|
317
|
+
src/dev_audit/
|
|
318
|
+
├── audit.py
|
|
319
|
+
├── cli.py
|
|
320
|
+
├── command.py
|
|
321
|
+
├── output.py
|
|
322
|
+
├── status.py
|
|
323
|
+
└── collectors/
|
|
324
|
+
├── system.py
|
|
325
|
+
├── resources.py
|
|
326
|
+
├── network.py
|
|
327
|
+
└── devtools.py
|
|
328
|
+
|
|
329
|
+
tests/
|
|
330
|
+
├── test_audit.py
|
|
331
|
+
├── test_command.py
|
|
332
|
+
├── test_network.py
|
|
333
|
+
├── test_output.py
|
|
334
|
+
├── test_resources.py
|
|
335
|
+
├── test_status.py
|
|
336
|
+
└── test_system.py
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Roadmap
|
|
342
|
+
|
|
343
|
+
* GitHub Actions CI
|
|
344
|
+
* Coverage reporting
|
|
345
|
+
* Additional audit rules
|
|
346
|
+
* Package publishing
|
|
347
|
+
* Extended Linux distribution support
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
dev_audit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
dev_audit/__main__.py,sha256=NMzkhEt4JrPnvOKaIX-PS41GmT7WtA8wdimlZJYB4Ro,88
|
|
3
|
+
dev_audit/audit.py,sha256=6Oi2QCETVvZuA1yfyvJ0-RgiwxdAv5szDKK4BSdrO9s,1276
|
|
4
|
+
dev_audit/cli.py,sha256=mBGVVT_ufyKmy88SECDiiVxroqrAO1D8TcW63RDeM68,2985
|
|
5
|
+
dev_audit/command.py,sha256=ZBqdolTIUgWLWmHEeZrHPw_Td9p-umQxl6uKFeq3ivw,1233
|
|
6
|
+
dev_audit/output.py,sha256=1LGoiRWbCsuupz3vI8B9H3VdHb1rcT3qclFYTaFbk3A,7297
|
|
7
|
+
dev_audit/status.py,sha256=cdbbDP7aSyL4j7G28wzlweKTvEd1nlPRf9v-IC0fKvQ,605
|
|
8
|
+
dev_audit/collectors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
dev_audit/collectors/devtools.py,sha256=nNkRV6lCuJ5aS86V8ltCcT7NMFLRFGRF2SKXjx_NHoA,2671
|
|
10
|
+
dev_audit/collectors/network.py,sha256=LrBvQNmHJ5eF1Zz0nTYwyBWo7Yw2ghg6HDkEnDLXmWo,4020
|
|
11
|
+
dev_audit/collectors/resources.py,sha256=5Gc3cpaJVxF2b-a1E70y35d1FYypZL_D3jiJGw7Ixic,3706
|
|
12
|
+
dev_audit/collectors/system.py,sha256=J2bzNOtI4eVGkhzEll498iGNq6maTglmixkxnEeJm68,1739
|
|
13
|
+
devaudit_cli-0.3.0.dist-info/licenses/LICENSE,sha256=-7gN4WoZV6NAULFetK8ovhVGWD7_BkEt1qcTFryzWDw,1092
|
|
14
|
+
devaudit_cli-0.3.0.dist-info/METADATA,sha256=xvqqCiql_fIOITr4ffThGiQ36BH6iPQDVCvnzADNX80,6631
|
|
15
|
+
devaudit_cli-0.3.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
16
|
+
devaudit_cli-0.3.0.dist-info/entry_points.txt,sha256=3ONwyrlQeBsW4d3u6QG6NYrzSxgsDVS3kt6txVBtOu4,49
|
|
17
|
+
devaudit_cli-0.3.0.dist-info/top_level.txt,sha256=RApWYjNVDZXVB3dwjgw7UHrD8ujDknaeP8T12QBA0nk,10
|
|
18
|
+
devaudit_cli-0.3.0.dist-info/RECORD,,
|