code-audit-23 0.1.1__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.
File without changes
@@ -0,0 +1,62 @@
1
+ import logging
2
+ import os
3
+ import sys
4
+ from logging.handlers import RotatingFileHandler
5
+ from pathlib import Path
6
+
7
+ from dotenv import load_dotenv
8
+
9
+ load_dotenv()
10
+
11
+ LOG_LEVEL = os.getenv("LOG_LEVEL", "WARNING").upper()
12
+
13
+
14
+ def setup_logger(name):
15
+ """
16
+ Set up a logger with both file and console handlers.
17
+ Logs are stored in the directory where the command is executed.
18
+ """
19
+
20
+ # Always use the current working directory for logs
21
+ log_dir = Path.cwd() / "logs"
22
+
23
+ # Create logs directory if missing
24
+ log_dir.mkdir(parents=True, exist_ok=True)
25
+
26
+ # Initialize logger
27
+ logger = logging.getLogger(name)
28
+ logger.setLevel(LOG_LEVEL)
29
+
30
+ # Prevent duplicate handlers
31
+ if logger.hasHandlers():
32
+ return logger
33
+
34
+ # Formatters
35
+ file_formatter = logging.Formatter(
36
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
37
+ datefmt="%Y-%m-%d %H:%M:%S",
38
+ )
39
+ console_formatter = logging.Formatter("%(levelname)-8s %(message)s")
40
+
41
+ # File handler (rotating)
42
+ log_file = log_dir / "audit_scanner.log"
43
+ file_handler = RotatingFileHandler(
44
+ log_file, maxBytes=5 * 1024 * 1024, backupCount=3, encoding="utf-8"
45
+ )
46
+ file_handler.setLevel(LOG_LEVEL)
47
+ file_handler.setFormatter(file_formatter)
48
+
49
+ # Console handler
50
+ console_handler = logging.StreamHandler()
51
+ console_handler.setLevel(LOG_LEVEL)
52
+ console_handler.setFormatter(console_formatter)
53
+
54
+ # Add handlers
55
+ logger.addHandler(file_handler)
56
+ logger.addHandler(console_handler)
57
+
58
+ return logger
59
+
60
+
61
+ # Default logger instance
62
+ logger = setup_logger(__name__)
code_audit_23/main.py ADDED
@@ -0,0 +1,286 @@
1
+ import os
2
+ import subprocess
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ import click
7
+ from dotenv import load_dotenv
8
+
9
+ # Allow running both as package and script
10
+ if __package__ is None or __package__ == "":
11
+ # Running as script (e.g. python main.py)
12
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
13
+ from logger import logger
14
+ from sonarqube_cli import run_sonarqube_scan
15
+ from trivy_cli import run_trivy_scan
16
+ else:
17
+ # Running as installed package
18
+ from .logger import logger
19
+ from .sonarqube_cli import run_sonarqube_scan
20
+ from .trivy_cli import run_trivy_scan
21
+
22
+ # Load environment variables from .env file
23
+ load_dotenv()
24
+
25
+ # Default SonarQube configuration
26
+ SONAR_HOST_URL = os.getenv("SONAR_HOST_URL", None)
27
+ SONAR_LOGIN = os.getenv("SONAR_LOGIN", None)
28
+
29
+
30
+ def ensure_reports_dir():
31
+ """Ensure the reports directory exists"""
32
+ reports_dir = Path("reports")
33
+ reports_dir.mkdir(exist_ok=True)
34
+ return reports_dir
35
+
36
+
37
+ def get_sonarqube_credentials():
38
+ """Prompt user for SonarQube credentials if not in environment"""
39
+ click.echo(
40
+ click.style("\n🔑 SonarQube Configuration Required", fg="yellow", bold=True)
41
+ )
42
+ click.echo(click.style("-" * 40, fg="bright_black"))
43
+ sonar_url = click.prompt(
44
+ click.style(
45
+ "Enter SonarQube URL (e.g., http://localhost:9000)", fg="bright_cyan"
46
+ ),
47
+ type=str,
48
+ )
49
+ sonar_token = click.prompt(
50
+ click.style("Enter SonarQube Token (will be hidden)", fg="bright_cyan"),
51
+ hide_input=True,
52
+ )
53
+ click.echo(click.style("✅ Credentials saved for this session\n", fg="green"))
54
+ return sonar_url, sonar_token
55
+
56
+
57
+ def show_welcome_banner():
58
+ """Display welcome banner with ASCII art"""
59
+ banner = """
60
+ ██████╗ ██████╗ ██████╗ ███████╗ █████╗ ██╗ ██╗██████╗ ██╗████████╗ ██████╗ ██████╗
61
+ ██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██╔══██╗██║ ██║██╔══██╗██║╚══██╔══╝ ╚════██╗╚════██╗
62
+ ██║ ██║ ██║██║ ██║█████╗ ███████║██║ ██║██║ ██║██║ ██║ █████╔╝ █████╔╝
63
+ ██║ ██║ ██║██║ ██║██╔══╝ ██╔══██║██║ ██║██║ ██║██║ ██║ ██╔═══╝ ╚═══██╗
64
+ ╚██████╗╚██████╔╝██████╔╝███████╗ ██║ ██║╚██████╔╝██████╔╝██║ ██║ ███████╗██████╔╝
65
+ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚═════╝
66
+ """
67
+ click.echo(click.style(banner, fg="bright_cyan"))
68
+ click.echo(
69
+ click.style(
70
+ " " * 25 + "🚀 Code Quality & Security Scanner 🚀\n",
71
+ fg="bright_white",
72
+ bold=True,
73
+ )
74
+ )
75
+ click.echo(click.style(" " * 30 + "Version 1.0.0\n", fg="bright_black"))
76
+
77
+ # Ensure reports directory exists
78
+ ensure_reports_dir()
79
+
80
+
81
+ def show_menu():
82
+ """Display main interactive menu"""
83
+ click.echo(click.style("\n" + "═" * 80, fg="bright_blue"))
84
+ click.echo(
85
+ click.style(
86
+ " " * 22 + "🔍 CODE AUDIT 23 MENU 🔍", fg="bright_cyan", bold=True
87
+ )
88
+ )
89
+ click.echo(click.style("═" * 80 + "\n", fg="bright_blue"))
90
+
91
+ menu_items = [
92
+ (
93
+ "1",
94
+ "Quick Scan (SonarQube + Gitleaks + Trivy)",
95
+ "Run all security scans in sequence",
96
+ ),
97
+ (
98
+ "2",
99
+ "Trivy Scan",
100
+ "Scan for vulnerabilities in dependencies and container images",
101
+ ),
102
+ ("3", "SonarQube Scan", "Analyze code quality and security issues"),
103
+ ("q", "Quit", "Exit the application"),
104
+ ]
105
+
106
+ for num, title, desc in menu_items:
107
+ click.echo(
108
+ click.style(f" [{num}] ", fg="bright_green", bold=True)
109
+ + click.style(f"{title}", fg="white", bold=True)
110
+ )
111
+ click.echo(click.style(f" {desc}", fg="bright_black"))
112
+ # click.echo()
113
+
114
+ click.echo(click.style("─" * 80, fg="bright_blue"))
115
+
116
+
117
+ def prompt_choice():
118
+ """Prompt user for menu selection with validation"""
119
+ while True:
120
+ choice = (
121
+ click.prompt(
122
+ click.style("\nSelect an option", fg="bright_yellow"),
123
+ type=str,
124
+ default="1",
125
+ show_default=False,
126
+ )
127
+ .strip()
128
+ .lower()
129
+ )
130
+
131
+ if choice in ["1", "2", "3", "4", "q", "quit"]:
132
+ return choice
133
+ click.echo(
134
+ click.style(
135
+ "❌ Invalid choice. Please select 1, 2, 3, or q to quit.", fg="red"
136
+ )
137
+ )
138
+
139
+
140
+ def main():
141
+ """Interactive entrypoint for Audit Scanner"""
142
+ # Clear screen and show welcome banner
143
+ click.clear()
144
+ show_welcome_banner()
145
+
146
+ # Initialize SonarQube credentials
147
+ global SONAR_HOST_URL, SONAR_LOGIN
148
+ sonar_credentials_provided = bool(SONAR_HOST_URL and SONAR_LOGIN)
149
+
150
+ while True:
151
+ try:
152
+ show_menu()
153
+ choice = prompt_choice()
154
+ # click.clear()
155
+
156
+ # Handle quit option
157
+ if choice.lower() in ["q", "quit"]:
158
+ click.echo(
159
+ click.style(
160
+ "\n👋 Thank you for using Code Audit 23. Goodbye!\n",
161
+ fg="bright_blue",
162
+ bold=True,
163
+ )
164
+ )
165
+ break
166
+
167
+ # Run Trivy scan for Quick Scan or Trivy only
168
+ if choice in ["1", "2"]:
169
+ if choice == "1":
170
+ click.echo("\n" + "─" * 80)
171
+ report_path = "reports/trivy.sarif"
172
+ click.echo(
173
+ click.style(
174
+ f"🔍 Starting Trivy Vulnerability Scan... (Report will be saved to {report_path})",
175
+ fg="bright_cyan",
176
+ bold=True,
177
+ )
178
+ )
179
+ # subprocess.run([
180
+ # "trivy",
181
+ # "repository",
182
+ # "--format", "sarif",
183
+ # "--output", report_path,
184
+ # "."
185
+ # ], check=True)
186
+ run_trivy_scan(report_path)
187
+ if choice == "2":
188
+ click.echo(
189
+ click.style(
190
+ f"\n✅ Trivy Scan completed successfully! Report saved to {report_path}",
191
+ fg="bright_green",
192
+ bold=True,
193
+ )
194
+ )
195
+
196
+ # Run SonarQube scan for Quick Scan or SonarQube only
197
+ if choice in ["1", "3"]:
198
+ if choice == "1":
199
+ click.echo("\n" + "─" * 80)
200
+ click.echo(
201
+ click.style(
202
+ "🚀 Starting SonarQube Scan...", fg="bright_cyan", bold=True
203
+ )
204
+ )
205
+ try:
206
+ # Get credentials if not already provided
207
+ if not sonar_credentials_provided:
208
+ SONAR_HOST_URL, SONAR_LOGIN = get_sonarqube_credentials()
209
+ sonar_credentials_provided = True
210
+
211
+ run_sonarqube_scan(
212
+ sonar_url=SONAR_HOST_URL,
213
+ token=SONAR_LOGIN,
214
+ project_key=None,
215
+ sources=".",
216
+ )
217
+ except Exception as e:
218
+ logger.error(f"SonarQube scan failed: {e}")
219
+ click.echo(
220
+ click.style(f"❌ SonarQube scan failed: {str(e)}", fg="red")
221
+ )
222
+ if click.confirm(
223
+ click.style(
224
+ "Do you want to update SonarQube credentials?", fg="yellow"
225
+ )
226
+ ):
227
+ sonar_url, sonar_token = get_sonarqube_credentials()
228
+ SONAR_HOST_URL = sonar_url
229
+ SONAR_LOGIN = sonar_token
230
+ # Retry the scan with new credentials
231
+ run_sonarqube_scan(
232
+ sonar_url=SONAR_HOST_URL,
233
+ token=SONAR_LOGIN,
234
+ project_key=None,
235
+ sources=".",
236
+ )
237
+ if choice == "3":
238
+ click.echo(
239
+ click.style(
240
+ "\n✅ SonarQube Scan completed successfully!",
241
+ fg="bright_green",
242
+ bold=True,
243
+ )
244
+ )
245
+
246
+ # Show completion message for Quick Scan
247
+ if choice == "1":
248
+ click.echo("\n" + "=" * 80)
249
+ click.echo(
250
+ click.style(
251
+ "✅ Quick Scan completed successfully!",
252
+ fg="bright_green",
253
+ bold=True,
254
+ )
255
+ )
256
+ click.echo(click.style("=" * 80 + "\n", fg="bright_green"))
257
+
258
+ # # Ask if user wants to perform another scan
259
+ # click.echo("\n" + "─" * 80)
260
+ # if not click.confirm(click.style("Would you like to perform another scan?", fg='bright_yellow')):
261
+ # click.echo(click.style("\n👋 Thank you for using Code Audit 23. Goodbye!\n", fg='bright_blue', bold=True))
262
+ # break
263
+
264
+ # click.clear()
265
+ # show_welcome_banner()
266
+
267
+ except Exception as e:
268
+ logger.error(f"Scan failed: {e}")
269
+ click.echo(click.style("\n❌ An error occurred during the scan.", fg="red"))
270
+ if not click.confirm(
271
+ click.style("Would you like to try again?", fg="yellow")
272
+ ):
273
+ click.echo(
274
+ click.style(
275
+ "\n👋 Thank you for using Code Audit 23. Goodbye!\n",
276
+ fg="bright_blue",
277
+ bold=True,
278
+ )
279
+ )
280
+ break
281
+ # click.clear()
282
+ # show_welcome_banner()
283
+
284
+
285
+ if __name__ == "__main__":
286
+ main()
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env sh
2
+ #
3
+ # SonarScanner CLI Startup Script for Unix
4
+ #
5
+ # Required ENV vars:
6
+ # JAVA_HOME - Location of Java's installation, optional if use_embedded_jre is set
7
+ #
8
+ # Optional ENV vars:
9
+ # SONAR_SCANNER_OPTS - Parameters passed to the Java VM when running the SonarScanner
10
+ # SONAR_SCANNER_DEBUG_OPTS - Extra parameters passed to the Java VM for debugging
11
+
12
+ real_path () {
13
+ target=$1
14
+
15
+ (
16
+ while true; do
17
+ cd "`dirname "$target"`"
18
+ target=`basename "$target"`
19
+ test -L "$target" || break
20
+ target=`readlink "$target"`
21
+ done
22
+
23
+ echo "`pwd -P`/$target"
24
+ )
25
+ }
26
+
27
+ script_path=`real_path "$0"`
28
+ sonar_scanner_home=`dirname "$script_path"`/..
29
+
30
+ # make it fully qualified
31
+ sonar_scanner_home=`cd "$sonar_scanner_home" && pwd -P`
32
+
33
+ jar_file=$sonar_scanner_home/lib/sonar-scanner-cli-7.3.0.5189.jar
34
+
35
+ # check that sonar_scanner_home has been correctly set
36
+ if [ ! -f "$jar_file" ] ; then
37
+ echo "File does not exist: $jar_file"
38
+ echo "'$sonar_scanner_home' does not point to a valid installation directory: $sonar_scanner_home"
39
+ exit 1
40
+ fi
41
+
42
+ use_embedded_jre=false
43
+ if [ "$use_embedded_jre" = true ]; then
44
+ export JAVA_HOME="$sonar_scanner_home/jre"
45
+ fi
46
+
47
+ if [ -n "$JAVA_HOME" ]
48
+ then
49
+ java_cmd="$JAVA_HOME/bin/java"
50
+ else
51
+ java_cmd="`\\unset -f command; \\command -v java`"
52
+ fi
53
+
54
+ if [ -z "$java_cmd" -o ! -x "$java_cmd" ] ; then
55
+ echo "Could not find 'java' executable in JAVA_HOME or PATH."
56
+ exit 1
57
+ fi
58
+
59
+ project_home=`pwd`
60
+
61
+ #echo "Info: Using sonar-scanner at $sonar_scanner_home"
62
+ #echo "Info: Using java at $java_cmd"
63
+ #echo "Info: Using classpath $jar_file"
64
+ #echo "Info: Using project $project_home"
65
+
66
+ exec "$java_cmd" \
67
+ -Djava.awt.headless=true \
68
+ $SONAR_SCANNER_OPTS \
69
+ $SONAR_SCANNER_DEBUG_OPTS \
70
+ -classpath "$jar_file" \
71
+ -Dscanner.home="$sonar_scanner_home" \
72
+ -Dproject.home="$project_home" \
73
+ org.sonarsource.scanner.cli.Main "$@"
74
+
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env sh
2
+ #
3
+ # SonarScanner CLI Startup Script for Unix
4
+ #
5
+ # Required ENV vars:
6
+ # JAVA_HOME - Location of Java's installation, optional if use_embedded_jre is set
7
+ #
8
+ # Optional ENV vars:
9
+ # SONAR_SCANNER_OPTS - parameters passed to the Java VM when running the SonarScanner
10
+
11
+ SONAR_SCANNER_DEBUG_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000"
12
+ SONAR_SCANNER_JAVA_DEBUG_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8001"
13
+ SONAR_SCANNER_JAVA_OPTS="$SONAR_SCANNER_JAVA_OPTS $SONAR_SCANNER_JAVA_DEBUG_OPTS"
14
+
15
+ echo "Executing SonarScanner CLI in Debug Mode"
16
+ echo "SONAR_SCANNER_DEBUG_OPTS=\"$SONAR_SCANNER_DEBUG_OPTS\""
17
+ echo "SONAR_SCANNER_JAVA_OPTS=\"$SONAR_SCANNER_JAVA_OPTS\""
18
+
19
+ env SONAR_SCANNER_OPTS="$SONAR_SCANNER_OPTS" SONAR_SCANNER_DEBUG_OPTS="$SONAR_SCANNER_DEBUG_OPTS" SONAR_SCANNER_JAVA_OPTS="$SONAR_SCANNER_JAVA_OPTS" "`dirname "$0"`"/sonar-scanner "$@"
@@ -0,0 +1,18 @@
1
+ @REM SonarScanner CLI Startup Script for Windows
2
+ @REM
3
+ @REM Required ENV vars:
4
+ @REM JAVA_HOME - Location of Java's installation, optional if use_embedded_jre is set
5
+ @REM
6
+ @REM Optional ENV vars:
7
+ @REM SONAR_SCANNER_OPTS - parameters passed to the Java VM when running the SonarScanner
8
+
9
+ @setlocal
10
+ @set SONAR_SCANNER_DEBUG_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
11
+ @set SONAR_SCANNER_JAVA_DEBUG_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8001
12
+
13
+ @set SONAR_SCANNER_JAVA_OPTS=$SONAR_SCANNER_JAVA_OPTS $SONAR_SCANNER_JAVA_DEBUG_OPTS
14
+
15
+ echo "Executing SonarScanner CLI in Debug Mode"
16
+ echo "SONAR_SCANNER_DEBUG_OPTS=%SONAR_SCANNER_DEBUG_OPTS%"
17
+ echo "SONAR_SCANNER_JAVA_OPTS=%SONAR_SCANNER_JAVA_OPTS%"
18
+ @call "%~dp0"sonar-scanner.bat %*
@@ -0,0 +1,92 @@
1
+ @REM SonarScanner CLI Startup Script for Windows
2
+ @REM
3
+ @REM Required ENV vars:
4
+ @REM JAVA_HOME - Location of Java's installation, optional if use_embedded_jre is set
5
+ @REM
6
+ @REM Optional ENV vars:
7
+ @REM SONAR_SCANNER_OPTS - parameters passed to the Java VM when running the SonarScanner
8
+ @REM SONAR_SCANNER_DEBUG_OPTS - Extra parameters passed to the Java VM for debugging
9
+
10
+ @echo off
11
+
12
+ set ERROR_CODE=0
13
+
14
+ @REM set local scope for the variables with windows NT shell
15
+ @setlocal
16
+
17
+ set "scriptdir=%~dp0"
18
+ if #%scriptdir:~-1%# == #\# set scriptdir=%scriptdir:~0,-1%
19
+ set "SONAR_SCANNER_HOME=%scriptdir%\.."
20
+
21
+ @REM ==== START VALIDATION ====
22
+ @REM *** JAVA EXEC VALIDATION ***
23
+
24
+ set use_embedded_jre=false
25
+ if "%use_embedded_jre%" == "true" (
26
+ set "JAVA_HOME=%SONAR_SCANNER_HOME%\jre"
27
+ )
28
+
29
+ if not "%JAVA_HOME%" == "" goto foundJavaHome
30
+
31
+ for %%i in (java.exe) do set JAVA_EXEC=%%~$PATH:i
32
+
33
+ if not "%JAVA_EXEC%" == "" (
34
+ set JAVA_EXEC="%JAVA_EXEC%"
35
+ goto OkJava
36
+ )
37
+
38
+ if not "%JAVA_EXEC%" == "" goto OkJava
39
+
40
+ echo.
41
+ echo ERROR: JAVA_HOME not found in your environment, and no Java
42
+ echo executable present in the PATH.
43
+ echo Please set the JAVA_HOME variable in your environment to match the
44
+ echo location of your Java installation, or add "java.exe" to the PATH
45
+ echo.
46
+ goto error
47
+
48
+ :foundJavaHome
49
+ if EXIST "%JAVA_HOME%\bin\java.exe" goto foundJavaExeFromJavaHome
50
+
51
+ echo.
52
+ echo ERROR: JAVA_HOME exists but does not point to a valid Java home
53
+ echo folder. No "\bin\java.exe" file can be found there.
54
+ echo.
55
+ goto error
56
+
57
+ :foundJavaExeFromJavaHome
58
+ set JAVA_EXEC="%JAVA_HOME%\bin\java.exe"
59
+
60
+ :OkJava
61
+ goto run
62
+
63
+
64
+ @REM ==== START RUN ====
65
+ :run
66
+
67
+ set PROJECT_HOME=%CD%
68
+
69
+ @REM remove trailing backslash, see https://groups.google.com/d/msg/sonarqube/wi7u-CyV_tc/3u9UKRmABQAJ
70
+ IF %PROJECT_HOME:~-1% == \ SET PROJECT_HOME=%PROJECT_HOME:~0,-1%
71
+
72
+ %JAVA_EXEC% -Djava.awt.headless=true %SONAR_SCANNER_DEBUG_OPTS% %SONAR_SCANNER_OPTS% -cp "%SONAR_SCANNER_HOME%\lib\sonar-scanner-cli-7.3.0.5189.jar" "-Dscanner.home=%SONAR_SCANNER_HOME%" "-Dproject.home=%PROJECT_HOME%" org.sonarsource.scanner.cli.Main %*
73
+ if ERRORLEVEL 1 goto error
74
+ goto end
75
+
76
+ :error
77
+ set ERROR_CODE=1
78
+
79
+ @REM ==== END EXECUTION ====
80
+
81
+ :end
82
+ @REM set local scope for the variables with windows NT shell
83
+ @endlocal & set ERROR_CODE=%ERROR_CODE%
84
+
85
+ @REM see http://code-bear.com/bearlog/2007/06/01/getting-the-exit-code-from-a-batch-file-that-is-run-from-a-python-program/
86
+ goto exit
87
+
88
+ :returncode
89
+ exit /B %1
90
+
91
+ :exit
92
+ call :returncode %ERROR_CODE%
@@ -0,0 +1,8 @@
1
+ # Configure here general information about the environment, such as the server connection details for example
2
+ # No information about specific project should appear here
3
+
4
+ #----- SonarQube server URL (default to SonarCloud)
5
+ #sonar.host.url=https://mycompany.com/sonarqube
6
+
7
+ #sonar.scanner.proxyHost=myproxy.mycompany.com
8
+ #sonar.scanner.proxyPort=8002