-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscanner.py
More file actions
139 lines (131 loc) · 5.49 KB
/
scanner.py
File metadata and controls
139 lines (131 loc) · 5.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env python3
"""
DevSec Scanner unified CLI
Usage:
./scanner [firebase|git|s3] --path <target> [--output <file>] [--format <json|text>] [--severity <level>]
"""
import sys
import os
import argparse
import time
import logging
from rich.console import Console
from rich.table import Table
from rich.progress import Progress
from src.devsec_scanner.scanners.firebase_scanner import scan_firebase
from src.devsec_scanner.scanners.git_secrets_scanner import scan_git_secrets
from src.devsec_scanner.scanners.s3_scanner import s3_scan_cli
# Setup logging
logging.basicConfig(level=logging.INFO, format='[%(levelname)s] %(message)s')
console = Console()
def main():
parser = argparse.ArgumentParser(
description="DevSec Scanner: Unified Security Scanning CLI"
)
subparsers = parser.add_subparsers(dest="scanner", required=True, help="Scanner type")
# Common arguments
def add_common_args(p):
p.add_argument('--path', '-p', required=False, help='Target path (file, directory, or repo)')
p.add_argument('--output', '-o', help='Output file (default: stdout)')
p.add_argument('--format', '-f', choices=['json', 'text'], default='text', help='Output format')
p.add_argument('--severity', '-s', choices=['low', 'medium', 'high'], help='Minimum severity to report')
# Firebase subcommand
parser_firebase = subparsers.add_parser('firebase', help='Scan Firebase project/rules')
add_common_args(parser_firebase)
# Git subcommand
parser_git = subparsers.add_parser('git', help='Scan Git repository for secrets')
add_common_args(parser_git)
# S3 subcommand
parser_s3 = subparsers.add_parser('s3', help='Scan AWS S3 buckets for security issues')
parser_s3.add_argument('--profile', help='AWS profile name')
parser_s3.add_argument('--region', action='append', help='Target AWS region(s)')
parser_s3.add_argument('--bucket-name', help='Scan a specific bucket only')
parser_s3.add_argument('--check-encryption', action='store_true', help='Check for encryption only')
parser_s3.add_argument('--format', choices=['text', 'json', 'csv'], default='text', help='Output format')
parser_s3.add_argument('--output', help='Export results to file')
args = parser.parse_args()
start_time = time.time()
exit_code = 0
try:
if args.scanner == 'firebase':
with Progress() as progress:
task = progress.add_task("[cyan]Scanning Firebase...", total=1)
results = scan_firebase(
path=args.path,
output=args.output,
output_format=args.format,
severity=args.severity,
progress=progress,
task=task
)
progress.update(task, advance=1)
# Output handling
if args.output:
with open(args.output, 'w') as f:
if args.format == 'json':
import json
json.dump(results, f, indent=2)
else:
f.write(results if isinstance(results, str) else str(results))
else:
if args.format == 'json':
import json
console.print_json(data=results)
else:
console.print(results)
# Exit code logic
if results and (isinstance(results, dict) and results.get('findings')):
exit_code = 1
elif results and isinstance(results, list) and len(results) > 0:
exit_code = 1
else:
exit_code = 0
elif args.scanner == 'git':
with Progress() as progress:
task = progress.add_task("[magenta]Scanning Git repo...", total=1)
results = scan_git_secrets(
path=args.path,
output=args.output,
output_format=args.format,
severity=args.severity,
progress=progress,
task=task
)
progress.update(task, advance=1)
# Output handling
if args.output:
with open(args.output, 'w') as f:
if args.format == 'json':
import json
json.dump(results, f, indent=2)
else:
f.write(results if isinstance(results, str) else str(results))
else:
if args.format == 'json':
import json
console.print_json(data=results)
else:
console.print(results)
# Exit code logic
if results and (isinstance(results, dict) and results.get('findings')):
exit_code = 1
elif results and isinstance(results, list) and len(results) > 0:
exit_code = 1
else:
exit_code = 0
elif args.scanner == 's3':
# Delegate to s3_scan_cli for full argument parsing and reporting
s3_scan_cli()
return # s3_scan_cli handles sys.exit
else:
parser.print_help()
sys.exit(2)
except Exception as e:
logging.error(f"Error: {e}")
exit_code = 2
finally:
elapsed = time.time() - start_time
console.print(f"[bold green]Scan completed in {elapsed:.2f}s")
sys.exit(exit_code)
if __name__ == "__main__":
main()