cycode 1.9.5.dev5__tar.gz → 1.9.6.dev2__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.
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/PKG-INFO +6 -3
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/README.md +5 -2
- cycode-1.9.6.dev2/cycode/__init__.py +1 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/auth/auth_manager.py +11 -11
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/common.py +1 -1
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/code_scanner.py +37 -29
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/pre_receive/pre_receive_command.py +5 -4
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/excluder.py +38 -11
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/path_documents.py +1 -1
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/sca/maven/base_restore_maven_dependencies.py +1 -1
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/sca/sca_code_scanner.py +6 -6
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/zip_documents.py +7 -6
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/progress_bar.py +11 -6
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/shell_executor.py +2 -2
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/config.py +18 -9
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/cycode_client_base.py +8 -2
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/headers.py +1 -1
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/pyproject.toml +2 -1
- cycode-1.9.5.dev5/cycode/__init__.py +0 -1
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/auth/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/auth/auth_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/configure/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/configure/configure_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/ignore/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/ignore/ignore_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/main_cli.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/report_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/path/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/path/path_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/repository_url/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/repository_url/repository_url_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/sbom_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/sbom_report_file.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/commit_history/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/commit_history/commit_history_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/path/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/path/path_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/pre_commit/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/pre_commit/pre_commit_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/pre_receive/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/repository/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/repository/repository_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/scan_ci/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/scan_ci/ci_integrations.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/scan_ci/scan_ci_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/scan_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/version/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/version/version_command.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/config.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/config.yaml +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/consts.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/exceptions/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/exceptions/custom_exceptions.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/exceptions/handle_report_sbom_errors.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/exceptions/handle_scan_errors.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/iac/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/iac/tf_content_generator.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/models/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/models/in_memory_zip.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/repository_documents.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/sca/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/sca/maven/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/main.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/models.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/console_printer.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/json_printer.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/printer_base.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/tables/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/tables/sca_table_printer.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/tables/table.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/tables/table_models.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/tables/table_printer.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/tables/table_printer_base.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/printers/text_printer.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/user_settings/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/user_settings/base_file_manager.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/user_settings/config_file_manager.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/user_settings/configuration_manager.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/user_settings/credentials_manager.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/user_settings/jwt_creator.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/enum_utils.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/get_api_client.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/path_utils.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/scan_batch.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/scan_utils.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/string_utils.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/task_timer.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/utils/yaml_utils.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/__init__.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/auth_client.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/client_creator.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/config.yaml +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/config_dev.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/cycode_client.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/cycode_dev_based_client.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/cycode_token_based_client.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/models.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/report_client.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/scan_client.py +0 -0
- {cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cyclient/scan_config_base.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cycode
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.6.dev2
|
|
4
4
|
Summary: Boost security in your dev lifecycle via SAST, SCA, Secrets & IaC scanning.
|
|
5
5
|
Home-page: https://github.com/cycodehq/cycode-cli
|
|
6
6
|
License: MIT
|
|
@@ -557,9 +557,12 @@ Secret SHA: a44081db3296c84b82d12a35c446a3cba19411dddfa0380134c75f7b3973bff0
|
|
|
557
557
|
|
|
558
558
|
### Soft Fail
|
|
559
559
|
|
|
560
|
-
|
|
560
|
+
Using the soft fail feature will not fail the CI/CD step within the pipeline if the Cycode scan detects an issue.
|
|
561
|
+
If an issue occurs during the Cycode scan, using a soft fail feature will automatically execute with success (`0`) to avoid interference.
|
|
561
562
|
|
|
562
|
-
|
|
563
|
+
To configure this feature, add the `--soft-fail` option to any type of scan. This will force the scan results to succeed (exit code `0`).
|
|
564
|
+
|
|
565
|
+
Scan results are assigned with a value of exit code `1` when issues are found in the scan results; this will result in a failure within the CI/CD tool. Use the option `--soft-fail` to force the results with the exit code `0` to have no impact (i.e., to have a successful result).
|
|
563
566
|
|
|
564
567
|
### Example Scan Results
|
|
565
568
|
|
|
@@ -519,9 +519,12 @@ Secret SHA: a44081db3296c84b82d12a35c446a3cba19411dddfa0380134c75f7b3973bff0
|
|
|
519
519
|
|
|
520
520
|
### Soft Fail
|
|
521
521
|
|
|
522
|
-
|
|
522
|
+
Using the soft fail feature will not fail the CI/CD step within the pipeline if the Cycode scan detects an issue.
|
|
523
|
+
If an issue occurs during the Cycode scan, using a soft fail feature will automatically execute with success (`0`) to avoid interference.
|
|
523
524
|
|
|
524
|
-
|
|
525
|
+
To configure this feature, add the `--soft-fail` option to any type of scan. This will force the scan results to succeed (exit code `0`).
|
|
526
|
+
|
|
527
|
+
Scan results are assigned with a value of exit code `1` when issues are found in the scan results; this will result in a failure within the CI/CD tool. Use the option `--soft-fail` to force the results with the exit code `0` to have no impact (i.e., to have a successful result).
|
|
525
528
|
|
|
526
529
|
### Example Scan Results
|
|
527
530
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '1.9.6.dev2' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
|
|
@@ -29,20 +29,20 @@ class AuthManager:
|
|
|
29
29
|
self.auth_client = AuthClient()
|
|
30
30
|
|
|
31
31
|
def authenticate(self) -> None:
|
|
32
|
-
logger.debug('
|
|
32
|
+
logger.debug('Generating PKCE code pair')
|
|
33
33
|
code_challenge, code_verifier = self._generate_pkce_code_pair()
|
|
34
34
|
|
|
35
|
-
logger.debug('
|
|
35
|
+
logger.debug('Starting authentication session')
|
|
36
36
|
session_id = self.start_session(code_challenge)
|
|
37
|
-
logger.debug('
|
|
37
|
+
logger.debug('Authentication session created, %s', {'session_id': session_id})
|
|
38
38
|
|
|
39
|
-
logger.debug('
|
|
39
|
+
logger.debug('Opening browser and redirecting to Cycode login page')
|
|
40
40
|
self.redirect_to_login_page(code_challenge, session_id)
|
|
41
41
|
|
|
42
|
-
logger.debug('
|
|
42
|
+
logger.debug('Getting API token')
|
|
43
43
|
api_token = self.get_api_token(session_id, code_verifier)
|
|
44
44
|
|
|
45
|
-
logger.debug('
|
|
45
|
+
logger.debug('Saving API token')
|
|
46
46
|
self.save_api_token(api_token)
|
|
47
47
|
|
|
48
48
|
def start_session(self, code_challenge: str) -> str:
|
|
@@ -56,20 +56,20 @@ class AuthManager:
|
|
|
56
56
|
def get_api_token(self, session_id: str, code_verifier: str) -> 'ApiToken':
|
|
57
57
|
api_token = self.get_api_token_polling(session_id, code_verifier)
|
|
58
58
|
if api_token is None:
|
|
59
|
-
raise AuthProcessError('
|
|
59
|
+
raise AuthProcessError('API token pulling is completed, but the token is missing')
|
|
60
60
|
return api_token
|
|
61
61
|
|
|
62
62
|
def get_api_token_polling(self, session_id: str, code_verifier: str) -> 'ApiToken':
|
|
63
63
|
end_polling_time = time.time() + self.POLLING_TIMEOUT_IN_SECONDS
|
|
64
64
|
while time.time() < end_polling_time:
|
|
65
|
-
logger.debug('
|
|
65
|
+
logger.debug('Trying to get API token...')
|
|
66
66
|
api_token_polling_response = self.auth_client.get_api_token(session_id, code_verifier)
|
|
67
67
|
if self._is_api_token_process_completed(api_token_polling_response):
|
|
68
|
-
logger.debug('
|
|
68
|
+
logger.debug('Got API token process completion response')
|
|
69
69
|
return api_token_polling_response.api_token
|
|
70
70
|
if self._is_api_token_process_failed(api_token_polling_response):
|
|
71
|
-
logger.debug('
|
|
72
|
-
raise AuthProcessError('
|
|
71
|
+
logger.debug('Got API token process failure response')
|
|
72
|
+
raise AuthProcessError('Error while obtaining API token')
|
|
73
73
|
time.sleep(self.POLLING_WAIT_INTERVAL_IN_SECONDS)
|
|
74
74
|
|
|
75
75
|
raise AuthProcessError('session expired')
|
|
@@ -70,7 +70,7 @@ def send_report_feedback(
|
|
|
70
70
|
|
|
71
71
|
client.report_status(report_execution_id, scan_status)
|
|
72
72
|
except Exception as e:
|
|
73
|
-
logger.debug(
|
|
73
|
+
logger.debug('Failed to send report feedback', exc_info=e)
|
|
74
74
|
|
|
75
75
|
|
|
76
76
|
def create_sbom_report(
|
|
@@ -200,7 +200,7 @@ def _get_scan_documents_thread_func(
|
|
|
200
200
|
scan_id = local_scan_result.scan_id
|
|
201
201
|
|
|
202
202
|
logger.debug(
|
|
203
|
-
'
|
|
203
|
+
'Processing scan results, %s',
|
|
204
204
|
{
|
|
205
205
|
'all_violations_count': detections_count,
|
|
206
206
|
'relevant_violations_count': relevant_detections_count,
|
|
@@ -246,14 +246,14 @@ def scan_commit_range(
|
|
|
246
246
|
|
|
247
247
|
repo = Repo(path)
|
|
248
248
|
total_commits_count = int(repo.git.rev_list('--count', commit_range))
|
|
249
|
-
logger.debug(
|
|
249
|
+
logger.debug('Calculating diffs for %s commits in the commit range %s', total_commits_count, commit_range)
|
|
250
250
|
|
|
251
251
|
progress_bar.set_section_length(ScanProgressBarSection.PREPARE_LOCAL_FILES, total_commits_count)
|
|
252
252
|
|
|
253
253
|
scanned_commits_count = 0
|
|
254
254
|
for commit in repo.iter_commits(rev=commit_range):
|
|
255
255
|
if _does_reach_to_max_commits_to_scan_limit(commit_ids_to_scan, max_commits_count):
|
|
256
|
-
logger.debug(
|
|
256
|
+
logger.debug('Reached to max commits to scan count. Going to scan only %s last commits', max_commits_count)
|
|
257
257
|
progress_bar.update(ScanProgressBarSection.PREPARE_LOCAL_FILES, total_commits_count - scanned_commits_count)
|
|
258
258
|
break
|
|
259
259
|
|
|
@@ -284,7 +284,7 @@ def scan_commit_range(
|
|
|
284
284
|
scanned_commits_count += 1
|
|
285
285
|
|
|
286
286
|
logger.debug('List of commit ids to scan, %s', {'commit_ids': commit_ids_to_scan})
|
|
287
|
-
logger.debug('Starting to scan commit range (
|
|
287
|
+
logger.debug('Starting to scan commit range (it may take a few minutes)')
|
|
288
288
|
|
|
289
289
|
scan_documents(context, documents_to_scan, is_git_diff=True, is_commit_range=True)
|
|
290
290
|
return None
|
|
@@ -307,7 +307,8 @@ def scan_documents(
|
|
|
307
307
|
ConsolePrinter(context).print_error(
|
|
308
308
|
CliError(
|
|
309
309
|
code='no_relevant_files',
|
|
310
|
-
message='Error: The scan could not be completed - relevant files to scan are not found.'
|
|
310
|
+
message='Error: The scan could not be completed - relevant files to scan are not found. '
|
|
311
|
+
'Enable verbose mode to see more details.',
|
|
311
312
|
)
|
|
312
313
|
)
|
|
313
314
|
return
|
|
@@ -392,7 +393,7 @@ def scan_commit_range_documents(
|
|
|
392
393
|
scan_id = local_scan_result.scan_id
|
|
393
394
|
|
|
394
395
|
logger.debug(
|
|
395
|
-
'
|
|
396
|
+
'Processing commit range scan results, %s',
|
|
396
397
|
{
|
|
397
398
|
'all_violations_count': detections_count,
|
|
398
399
|
'relevant_violations_count': relevant_detections_count,
|
|
@@ -475,7 +476,7 @@ def perform_scan_async(
|
|
|
475
476
|
scan_parameters: dict,
|
|
476
477
|
) -> ZippedFileScanResult:
|
|
477
478
|
scan_async_result = cycode_client.zipped_file_scan_async(zipped_documents, scan_type, scan_parameters)
|
|
478
|
-
logger.debug('scan request has been triggered successfully,
|
|
479
|
+
logger.debug('Async scan request has been triggered successfully, %s', {'scan_id': scan_async_result.scan_id})
|
|
479
480
|
|
|
480
481
|
return poll_scan_results(
|
|
481
482
|
cycode_client,
|
|
@@ -492,7 +493,7 @@ def perform_scan_sync(
|
|
|
492
493
|
scan_parameters: dict,
|
|
493
494
|
) -> ZippedFileScanResult:
|
|
494
495
|
scan_results = cycode_client.zipped_file_scan_sync(zipped_documents, scan_type, scan_parameters)
|
|
495
|
-
logger.debug('scan request has been triggered successfully,
|
|
496
|
+
logger.debug('Sync scan request has been triggered successfully, %s', {'scan_id': scan_results.id})
|
|
496
497
|
return ZippedFileScanResult(
|
|
497
498
|
did_detect=True,
|
|
498
499
|
detections_per_file=_map_detections_per_file(scan_results.detection_messages),
|
|
@@ -512,7 +513,9 @@ def perform_commit_range_scan_async(
|
|
|
512
513
|
from_commit_zipped_documents, to_commit_zipped_documents, scan_type, scan_parameters
|
|
513
514
|
)
|
|
514
515
|
|
|
515
|
-
logger.debug(
|
|
516
|
+
logger.debug(
|
|
517
|
+
'Async commit range scan request has been triggered successfully, %s', {'scan_id': scan_async_result.scan_id}
|
|
518
|
+
)
|
|
516
519
|
return poll_scan_results(
|
|
517
520
|
cycode_client, scan_async_result.scan_id, scan_type, scan_parameters.get('report'), timeout
|
|
518
521
|
)
|
|
@@ -552,11 +555,12 @@ def poll_scan_results(
|
|
|
552
555
|
|
|
553
556
|
|
|
554
557
|
def print_debug_scan_details(scan_details_response: 'ScanDetailsResponse') -> None:
|
|
555
|
-
logger.debug(
|
|
556
|
-
|
|
558
|
+
logger.debug(
|
|
559
|
+
'Scan update, %s', {'scan_id': scan_details_response.id, 'scan_status': scan_details_response.scan_status}
|
|
560
|
+
)
|
|
557
561
|
|
|
558
562
|
if scan_details_response.message:
|
|
559
|
-
logger.debug(
|
|
563
|
+
logger.debug('Scan message: %s', scan_details_response.message)
|
|
560
564
|
|
|
561
565
|
|
|
562
566
|
def print_results(
|
|
@@ -569,14 +573,16 @@ def print_results(
|
|
|
569
573
|
def get_document_detections(
|
|
570
574
|
scan_result: ZippedFileScanResult, documents_to_scan: List[Document]
|
|
571
575
|
) -> List[DocumentDetections]:
|
|
572
|
-
logger.debug('
|
|
576
|
+
logger.debug('Getting document detections')
|
|
573
577
|
|
|
574
578
|
document_detections = []
|
|
575
579
|
for detections_per_file in scan_result.detections_per_file:
|
|
576
580
|
file_name = get_path_by_os(detections_per_file.file_name)
|
|
577
581
|
commit_id = detections_per_file.commit_id
|
|
578
582
|
|
|
579
|
-
logger.debug(
|
|
583
|
+
logger.debug(
|
|
584
|
+
'Going to find the document of the violated file., %s', {'file_name': file_name, 'commit_id': commit_id}
|
|
585
|
+
)
|
|
580
586
|
|
|
581
587
|
document = _get_document_by_file_name(documents_to_scan, file_name, commit_id)
|
|
582
588
|
document_detections.append(DocumentDetections(document=document, detections=detections_per_file.detections))
|
|
@@ -659,10 +665,10 @@ def get_scan_parameters(context: click.Context, paths: Tuple[str]) -> dict:
|
|
|
659
665
|
def try_get_git_remote_url(path: str) -> Optional[str]:
|
|
660
666
|
try:
|
|
661
667
|
remote_url = Repo(path).remotes[0].config_reader.get('url')
|
|
662
|
-
logger.debug(
|
|
668
|
+
logger.debug('Found Git remote URL, %s', {'remote_url': remote_url, 'path': path})
|
|
663
669
|
return remote_url
|
|
664
670
|
except Exception as e:
|
|
665
|
-
logger.debug('Failed to get
|
|
671
|
+
logger.debug('Failed to get Git remote URL', exc_info=e)
|
|
666
672
|
return None
|
|
667
673
|
|
|
668
674
|
|
|
@@ -719,15 +725,15 @@ def _should_exclude_detection(detection: Detection, exclusions: Dict) -> bool:
|
|
|
719
725
|
exclusions_by_value = exclusions.get(consts.EXCLUSIONS_BY_VALUE_SECTION_NAME, [])
|
|
720
726
|
if _is_detection_sha_configured_in_exclusions(detection, exclusions_by_value):
|
|
721
727
|
logger.debug(
|
|
722
|
-
'Going to ignore violations because
|
|
723
|
-
{'
|
|
728
|
+
'Going to ignore violations because they are on the values-to-ignore list, %s',
|
|
729
|
+
{'value_sha': detection.detection_details.get('sha512', '')},
|
|
724
730
|
)
|
|
725
731
|
return True
|
|
726
732
|
|
|
727
733
|
exclusions_by_sha = exclusions.get(consts.EXCLUSIONS_BY_SHA_SECTION_NAME, [])
|
|
728
734
|
if _is_detection_sha_configured_in_exclusions(detection, exclusions_by_sha):
|
|
729
735
|
logger.debug(
|
|
730
|
-
'Going to ignore violations because
|
|
736
|
+
'Going to ignore violations because they are on the SHA ignore list, %s',
|
|
731
737
|
{'sha': detection.detection_details.get('sha512', '')},
|
|
732
738
|
)
|
|
733
739
|
return True
|
|
@@ -737,7 +743,7 @@ def _should_exclude_detection(detection: Detection, exclusions: Dict) -> bool:
|
|
|
737
743
|
detection_rule = detection.detection_rule_id
|
|
738
744
|
if detection_rule in exclusions_by_rule:
|
|
739
745
|
logger.debug(
|
|
740
|
-
'Going to ignore violations because
|
|
746
|
+
'Going to ignore violations because they are on the Rule ID ignore list, %s',
|
|
741
747
|
{'detection_rule': detection_rule},
|
|
742
748
|
)
|
|
743
749
|
return True
|
|
@@ -747,7 +753,7 @@ def _should_exclude_detection(detection: Detection, exclusions: Dict) -> bool:
|
|
|
747
753
|
package = _get_package_name(detection)
|
|
748
754
|
if package in exclusions_by_package:
|
|
749
755
|
logger.debug(
|
|
750
|
-
'Going to ignore violations because
|
|
756
|
+
'Going to ignore violations because they are on the packages-to-ignore list, %s', {'package': package}
|
|
751
757
|
)
|
|
752
758
|
return True
|
|
753
759
|
|
|
@@ -810,7 +816,7 @@ def _report_scan_status(
|
|
|
810
816
|
|
|
811
817
|
cycode_client.report_scan_status(scan_type, scan_id, scan_status, should_use_scan_service)
|
|
812
818
|
except Exception as e:
|
|
813
|
-
logger.debug('Failed to report scan status
|
|
819
|
+
logger.debug('Failed to report scan status', exc_info=e)
|
|
814
820
|
|
|
815
821
|
|
|
816
822
|
def _generate_unique_id() -> UUID:
|
|
@@ -868,7 +874,7 @@ def _try_get_report_url_if_needed(
|
|
|
868
874
|
report_url_response = cycode_client.get_scan_report_url(scan_id, scan_type)
|
|
869
875
|
return report_url_response.report_url
|
|
870
876
|
except Exception as e:
|
|
871
|
-
logger.debug('Failed to get report
|
|
877
|
+
logger.debug('Failed to get report URL', exc_info=e)
|
|
872
878
|
|
|
873
879
|
|
|
874
880
|
def wait_for_detections_creation(
|
|
@@ -883,16 +889,18 @@ def wait_for_detections_creation(
|
|
|
883
889
|
while time.time() < end_polling_time:
|
|
884
890
|
scan_persisted_detections_count = cycode_client.get_scan_detections_count(scan_type, scan_id)
|
|
885
891
|
logger.debug(
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
892
|
+
'Excepting %s detections, got %s detections (%s more; %s seconds left)',
|
|
893
|
+
expected_detections_count,
|
|
894
|
+
scan_persisted_detections_count,
|
|
895
|
+
expected_detections_count - scan_persisted_detections_count,
|
|
896
|
+
round(end_polling_time - time.time()),
|
|
889
897
|
)
|
|
890
898
|
if scan_persisted_detections_count == expected_detections_count:
|
|
891
899
|
return
|
|
892
900
|
|
|
893
901
|
time.sleep(consts.DETECTIONS_COUNT_VERIFICATION_WAIT_INTERVAL_IN_SECONDS)
|
|
894
902
|
|
|
895
|
-
logger.debug(
|
|
903
|
+
logger.debug('%s detections has been created', scan_persisted_detections_count)
|
|
896
904
|
raise custom_exceptions.ScanAsyncError(
|
|
897
905
|
f'Failed to wait for detections to be created after {polling_timeout} seconds'
|
|
898
906
|
)
|
|
@@ -905,14 +913,14 @@ def _map_detections_per_file(detections: List[dict]) -> List[DetectionsPerFile]:
|
|
|
905
913
|
detection['message'] = detection['correlation_message']
|
|
906
914
|
file_name = _get_file_name_from_detection(detection)
|
|
907
915
|
if file_name is None:
|
|
908
|
-
logger.debug('
|
|
916
|
+
logger.debug('File name is missing from detection with ID %s', detection.get('id'))
|
|
909
917
|
continue
|
|
910
918
|
if detections_per_files.get(file_name) is None:
|
|
911
919
|
detections_per_files[file_name] = [DetectionSchema().load(detection)]
|
|
912
920
|
else:
|
|
913
921
|
detections_per_files[file_name].append(DetectionSchema().load(detection))
|
|
914
922
|
except Exception as e:
|
|
915
|
-
logger.debug('Failed to parse detection
|
|
923
|
+
logger.debug('Failed to parse detection', exc_info=e)
|
|
916
924
|
continue
|
|
917
925
|
|
|
918
926
|
return [
|
{cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/pre_receive/pre_receive_command.py
RENAMED
|
@@ -32,14 +32,14 @@ def pre_receive_command(context: click.Context, ignored_args: List[str]) -> None
|
|
|
32
32
|
|
|
33
33
|
if should_skip_pre_receive_scan():
|
|
34
34
|
logger.info(
|
|
35
|
-
'A scan has been skipped as per your request.'
|
|
36
|
-
'
|
|
35
|
+
'A scan has been skipped as per your request. '
|
|
36
|
+
'Please note that this may leave your system vulnerable to secrets that have not been detected.'
|
|
37
37
|
)
|
|
38
38
|
return
|
|
39
39
|
|
|
40
40
|
if is_verbose_mode_requested_in_pre_receive_scan():
|
|
41
41
|
enable_verbose_mode(context)
|
|
42
|
-
logger.debug('Verbose mode enabled
|
|
42
|
+
logger.debug('Verbose mode enabled: all log levels will be displayed.')
|
|
43
43
|
|
|
44
44
|
command_scan_type = context.info_name
|
|
45
45
|
timeout = configuration_manager.get_pre_receive_command_timeout(command_scan_type)
|
|
@@ -51,7 +51,8 @@ def pre_receive_command(context: click.Context, ignored_args: List[str]) -> None
|
|
|
51
51
|
commit_range = calculate_pre_receive_commit_range(branch_update_details)
|
|
52
52
|
if not commit_range:
|
|
53
53
|
logger.info(
|
|
54
|
-
'No new commits found for pushed branch, %s',
|
|
54
|
+
'No new commits found for pushed branch, %s',
|
|
55
|
+
{'branch_update_details': branch_update_details},
|
|
55
56
|
)
|
|
56
57
|
return
|
|
57
58
|
|
|
@@ -62,23 +62,36 @@ def _does_document_exceed_max_size_limit(content: str) -> bool:
|
|
|
62
62
|
|
|
63
63
|
def _is_relevant_file_to_scan(scan_type: str, filename: str) -> bool:
|
|
64
64
|
if _is_subpath_of_cycode_configuration_folder(filename):
|
|
65
|
-
logger.debug(
|
|
65
|
+
logger.debug(
|
|
66
|
+
'The file is irrelevant because it is in the Cycode configuration directory, %s',
|
|
67
|
+
{'filename': filename, 'configuration_directory': consts.CYCODE_CONFIGURATION_DIRECTORY},
|
|
68
|
+
)
|
|
66
69
|
return False
|
|
67
70
|
|
|
68
71
|
if _is_path_configured_in_exclusions(scan_type, filename):
|
|
69
|
-
logger.debug('file is irrelevant because
|
|
72
|
+
logger.debug('The file is irrelevant because its path is in the ignore paths list, %s', {'filename': filename})
|
|
70
73
|
return False
|
|
71
74
|
|
|
72
75
|
if not _is_file_extension_supported(scan_type, filename):
|
|
73
|
-
logger.debug(
|
|
76
|
+
logger.debug(
|
|
77
|
+
'The file is irrelevant because its extension is not supported, %s',
|
|
78
|
+
{'scan_type': scan_type, 'filename': filename},
|
|
79
|
+
)
|
|
74
80
|
return False
|
|
75
81
|
|
|
76
82
|
if is_binary_file(filename):
|
|
77
|
-
logger.debug('file is irrelevant because it is binary file, %s', {'filename': filename})
|
|
83
|
+
logger.debug('The file is irrelevant because it is a binary file, %s', {'filename': filename})
|
|
78
84
|
return False
|
|
79
85
|
|
|
80
86
|
if scan_type != consts.SCA_SCAN_TYPE and _does_file_exceed_max_size_limit(filename):
|
|
81
|
-
logger.debug(
|
|
87
|
+
logger.debug(
|
|
88
|
+
'The file is irrelevant because it has exceeded the maximum size limit, %s',
|
|
89
|
+
{
|
|
90
|
+
'max_file_size': consts.FILE_MAX_SIZE_LIMIT_IN_BYTES,
|
|
91
|
+
'file_size': get_file_size(filename),
|
|
92
|
+
'filename': filename,
|
|
93
|
+
},
|
|
94
|
+
)
|
|
82
95
|
return False
|
|
83
96
|
|
|
84
97
|
if scan_type == consts.SCA_SCAN_TYPE and not _is_file_relevant_for_sca_scan(filename):
|
|
@@ -89,7 +102,9 @@ def _is_relevant_file_to_scan(scan_type: str, filename: str) -> bool:
|
|
|
89
102
|
|
|
90
103
|
def _is_file_relevant_for_sca_scan(filename: str) -> bool:
|
|
91
104
|
if any(sca_excluded_path in filename for sca_excluded_path in consts.SCA_EXCLUDED_PATHS):
|
|
92
|
-
logger.debug(
|
|
105
|
+
logger.debug(
|
|
106
|
+
'The file is irrelevant because it is from the inner path of node_modules, %s', {'filename': filename}
|
|
107
|
+
)
|
|
93
108
|
return False
|
|
94
109
|
|
|
95
110
|
return True
|
|
@@ -98,27 +113,39 @@ def _is_file_relevant_for_sca_scan(filename: str) -> bool:
|
|
|
98
113
|
def _is_relevant_document_to_scan(scan_type: str, filename: str, content: str) -> bool:
|
|
99
114
|
if _is_subpath_of_cycode_configuration_folder(filename):
|
|
100
115
|
logger.debug(
|
|
101
|
-
'document is irrelevant because it is in
|
|
116
|
+
'The document is irrelevant because it is in the Cycode configuration directory, %s',
|
|
117
|
+
{'filename': filename, 'configuration_directory': consts.CYCODE_CONFIGURATION_DIRECTORY},
|
|
102
118
|
)
|
|
103
119
|
return False
|
|
104
120
|
|
|
105
121
|
if _is_path_configured_in_exclusions(scan_type, filename):
|
|
106
122
|
logger.debug(
|
|
107
|
-
'document is irrelevant because
|
|
123
|
+
'The document is irrelevant because its path is in the ignore paths list, %s', {'filename': filename}
|
|
108
124
|
)
|
|
109
125
|
return False
|
|
110
126
|
|
|
111
127
|
if not _is_file_extension_supported(scan_type, filename):
|
|
112
|
-
logger.debug(
|
|
128
|
+
logger.debug(
|
|
129
|
+
'The document is irrelevant because its extension is not supported, %s',
|
|
130
|
+
{'scan_type': scan_type, 'filename': filename},
|
|
131
|
+
)
|
|
113
132
|
return False
|
|
114
133
|
|
|
115
134
|
if is_binary_content(content):
|
|
116
|
-
logger.debug('document is irrelevant because it is binary, %s', {'filename': filename})
|
|
135
|
+
logger.debug('The document is irrelevant because it is a binary file, %s', {'filename': filename})
|
|
117
136
|
return False
|
|
118
137
|
|
|
119
138
|
if scan_type != consts.SCA_SCAN_TYPE and _does_document_exceed_max_size_limit(content):
|
|
120
|
-
logger.debug(
|
|
139
|
+
logger.debug(
|
|
140
|
+
'The document is irrelevant because it has exceeded the maximum size limit, %s',
|
|
141
|
+
{
|
|
142
|
+
'max_document_size': consts.FILE_MAX_SIZE_LIMIT_IN_BYTES,
|
|
143
|
+
'document_size': get_content_size(content),
|
|
144
|
+
'filename': filename,
|
|
145
|
+
},
|
|
146
|
+
)
|
|
121
147
|
return False
|
|
148
|
+
|
|
122
149
|
return True
|
|
123
150
|
|
|
124
151
|
|
|
@@ -74,7 +74,7 @@ def _get_relevant_files(
|
|
|
74
74
|
progress_bar.set_section_length(progress_bar_section, progress_bar_section_len)
|
|
75
75
|
|
|
76
76
|
logger.debug(
|
|
77
|
-
'Found all relevant files for scanning %s', {'paths': paths, 'file_to_scan_count': len(relevant_files_to_scan)}
|
|
77
|
+
'Found all relevant files for scanning, %s', {'paths': paths, 'file_to_scan_count': len(relevant_files_to_scan)}
|
|
78
78
|
)
|
|
79
79
|
|
|
80
80
|
return relevant_files_to_scan
|
|
@@ -17,7 +17,7 @@ def execute_command(command: List[str], file_name: str, command_timeout: int) ->
|
|
|
17
17
|
try:
|
|
18
18
|
dependencies = shell(command, command_timeout)
|
|
19
19
|
except Exception as e:
|
|
20
|
-
logger.debug('Failed to restore dependencies shell
|
|
20
|
+
logger.debug('Failed to restore dependencies via shell command, %s', {'filename': file_name}, exc_info=e)
|
|
21
21
|
return None
|
|
22
22
|
|
|
23
23
|
return dependencies
|
|
@@ -47,7 +47,7 @@ def add_ecosystem_related_files_if_exists(
|
|
|
47
47
|
for doc in documents:
|
|
48
48
|
ecosystem = get_project_file_ecosystem(doc)
|
|
49
49
|
if ecosystem is None:
|
|
50
|
-
logger.debug('
|
|
50
|
+
logger.debug('Failed to resolve project file ecosystem: %s', doc.path)
|
|
51
51
|
continue
|
|
52
52
|
|
|
53
53
|
documents_to_add.extend(get_doc_ecosystem_related_project_files(doc, documents, ecosystem, commit_rev, repo))
|
|
@@ -94,20 +94,20 @@ def try_restore_dependencies(
|
|
|
94
94
|
if restore_dependencies.is_project(document):
|
|
95
95
|
restore_dependencies_document = restore_dependencies.restore(document)
|
|
96
96
|
if restore_dependencies_document is None:
|
|
97
|
-
logger.warning('Error occurred while trying to generate dependencies tree
|
|
97
|
+
logger.warning('Error occurred while trying to generate dependencies tree, %s', {'filename': document.path})
|
|
98
98
|
return
|
|
99
99
|
|
|
100
100
|
if restore_dependencies_document.content is None:
|
|
101
|
-
logger.warning('Error occurred while trying to generate dependencies tree
|
|
101
|
+
logger.warning('Error occurred while trying to generate dependencies tree, %s', {'filename': document.path})
|
|
102
102
|
restore_dependencies_document.content = ''
|
|
103
103
|
else:
|
|
104
104
|
is_monitor_action = context.obj.get('monitor')
|
|
105
105
|
project_path = context.params.get('path')
|
|
106
106
|
manifest_file_path = get_manifest_file_path(document, is_monitor_action, project_path)
|
|
107
|
-
logger.debug(
|
|
107
|
+
logger.debug('Succeeded to generate dependencies tree on path: %s', manifest_file_path)
|
|
108
108
|
|
|
109
109
|
if restore_dependencies_document.path in documents_to_add:
|
|
110
|
-
logger.debug(
|
|
110
|
+
logger.debug('Duplicate document on restore for path: %s', restore_dependencies_document.path)
|
|
111
111
|
else:
|
|
112
112
|
documents_to_add[restore_dependencies_document.path] = restore_dependencies_document
|
|
113
113
|
|
|
@@ -147,5 +147,5 @@ def perform_pre_scan_documents_actions(
|
|
|
147
147
|
context: click.Context, scan_type: str, documents_to_scan: List[Document], is_git_diff: bool = False
|
|
148
148
|
) -> None:
|
|
149
149
|
if scan_type == consts.SCA_SCAN_TYPE and not context.obj.get(consts.SCA_SKIP_RESTORE_DEPENDENCIES_FLAG):
|
|
150
|
-
logger.debug('Perform pre
|
|
150
|
+
logger.debug('Perform pre-scan document add_dependencies_tree_document action')
|
|
151
151
|
add_dependencies_tree_document(context, documents_to_scan, is_git_diff)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import timeit
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from typing import List, Optional
|
|
4
4
|
|
|
@@ -22,25 +22,26 @@ def zip_documents(scan_type: str, documents: List[Document], zip_file: Optional[
|
|
|
22
22
|
if zip_file is None:
|
|
23
23
|
zip_file = InMemoryZip()
|
|
24
24
|
|
|
25
|
-
start_zip_creation_time =
|
|
25
|
+
start_zip_creation_time = timeit.default_timer()
|
|
26
26
|
|
|
27
27
|
for index, document in enumerate(documents):
|
|
28
28
|
_validate_zip_file_size(scan_type, zip_file.size)
|
|
29
29
|
|
|
30
30
|
logger.debug(
|
|
31
|
-
'
|
|
31
|
+
'Adding file to ZIP, %s',
|
|
32
|
+
{'index': index, 'filename': document.path, 'unique_id': document.unique_id},
|
|
32
33
|
)
|
|
33
34
|
zip_file.append(document.path, document.unique_id, document.content)
|
|
34
35
|
|
|
35
36
|
zip_file.close()
|
|
36
37
|
|
|
37
|
-
end_zip_creation_time =
|
|
38
|
+
end_zip_creation_time = timeit.default_timer()
|
|
38
39
|
zip_creation_time = int(end_zip_creation_time - start_zip_creation_time)
|
|
39
|
-
logger.debug('
|
|
40
|
+
logger.debug('Finished to create ZIP file, %s', {'zip_creation_time': zip_creation_time})
|
|
40
41
|
|
|
41
42
|
if zip_file.configuration_manager.get_debug_flag():
|
|
42
43
|
zip_file_path = Path.joinpath(Path.cwd(), f'{scan_type}_scan_{end_zip_creation_time}.zip')
|
|
43
|
-
logger.debug('
|
|
44
|
+
logger.debug('Writing ZIP file to disk, %s', {'zip_file_path': zip_file_path})
|
|
44
45
|
zip_file.write_on_disk(zip_file_path)
|
|
45
46
|
|
|
46
47
|
return zip_file
|
|
@@ -11,8 +11,8 @@ if TYPE_CHECKING:
|
|
|
11
11
|
from click._termui_impl import ProgressBar
|
|
12
12
|
from click.termui import V as ProgressBarValue
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
logger = get_logger('progress bar')
|
|
14
|
+
# use LOGGING_LEVEL=DEBUG env var to see debug logs of this module
|
|
15
|
+
logger = get_logger('progress bar', control_level_in_runtime=False)
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class ProgressBarSection(AutoCountEnum):
|
|
@@ -184,7 +184,7 @@ class CompositeProgressBar(BaseProgressBar):
|
|
|
184
184
|
self.__exit__(None, None, None)
|
|
185
185
|
|
|
186
186
|
def set_section_length(self, section: 'ProgressBarSection', length: int = 0) -> None:
|
|
187
|
-
logger.debug(
|
|
187
|
+
logger.debug('Calling set_section_length, %s', {'section': str(section), 'length': length})
|
|
188
188
|
self._section_lengths[section] = length
|
|
189
189
|
|
|
190
190
|
if length == 0:
|
|
@@ -203,8 +203,11 @@ class CompositeProgressBar(BaseProgressBar):
|
|
|
203
203
|
def _increment_section_value(self, section: 'ProgressBarSection', value: int) -> None:
|
|
204
204
|
self._section_values[section] = self._section_values.get(section, 0) + value
|
|
205
205
|
logger.debug(
|
|
206
|
-
|
|
207
|
-
|
|
206
|
+
'Calling _increment_section_value: %s +%s. %s/%s',
|
|
207
|
+
section,
|
|
208
|
+
value,
|
|
209
|
+
self._section_values[section],
|
|
210
|
+
self._section_lengths[section],
|
|
208
211
|
)
|
|
209
212
|
|
|
210
213
|
def _rerender_progress_bar(self) -> None:
|
|
@@ -225,7 +228,9 @@ class CompositeProgressBar(BaseProgressBar):
|
|
|
225
228
|
cur_val = self._section_values.get(self._current_section.section, 0)
|
|
226
229
|
if cur_val >= max_val:
|
|
227
230
|
next_section = self._progress_bar_sections[self._current_section.section.next()]
|
|
228
|
-
logger.debug(
|
|
231
|
+
logger.debug(
|
|
232
|
+
'Calling _update_current_section: %s -> %s', self._current_section.section, next_section.section
|
|
233
|
+
)
|
|
229
234
|
|
|
230
235
|
self._current_section = next_section
|
|
231
236
|
self._current_section_value = 0
|
|
@@ -11,7 +11,7 @@ _SUBPROCESS_DEFAULT_TIMEOUT_SEC = 60
|
|
|
11
11
|
def shell(
|
|
12
12
|
command: Union[str, List[str]], timeout: int = _SUBPROCESS_DEFAULT_TIMEOUT_SEC, execute_in_shell: bool = False
|
|
13
13
|
) -> Optional[str]:
|
|
14
|
-
logger.debug(
|
|
14
|
+
logger.debug('Executing shell command: %s', command)
|
|
15
15
|
|
|
16
16
|
try:
|
|
17
17
|
result = subprocess.run(
|
|
@@ -24,7 +24,7 @@ def shell(
|
|
|
24
24
|
|
|
25
25
|
return result.stdout.decode('UTF-8').strip()
|
|
26
26
|
except subprocess.CalledProcessError as e:
|
|
27
|
-
logger.debug(
|
|
27
|
+
logger.debug('Error occurred while running shell command', exc_info=e)
|
|
28
28
|
except subprocess.TimeoutExpired as e:
|
|
29
29
|
raise click.Abort(f'Command "{command}" timed out') from e
|
|
30
30
|
except Exception as e:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
3
|
import sys
|
|
4
|
-
from typing import Optional, Union
|
|
4
|
+
from typing import NamedTuple, Optional, Set, Union
|
|
5
5
|
from urllib.parse import urlparse
|
|
6
6
|
|
|
7
7
|
from cycode.cli import consts
|
|
@@ -42,7 +42,13 @@ DEFAULT_CONFIGURATION = {
|
|
|
42
42
|
|
|
43
43
|
configuration = dict(DEFAULT_CONFIGURATION, **os.environ)
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
|
|
46
|
+
class CreatedLogger(NamedTuple):
|
|
47
|
+
logger: logging.Logger
|
|
48
|
+
control_level_in_runtime: bool
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
_CREATED_LOGGERS: Set[CreatedLogger] = set()
|
|
46
52
|
|
|
47
53
|
|
|
48
54
|
def get_logger_level() -> Optional[Union[int, str]]:
|
|
@@ -50,18 +56,19 @@ def get_logger_level() -> Optional[Union[int, str]]:
|
|
|
50
56
|
return logging.getLevelName(config_level)
|
|
51
57
|
|
|
52
58
|
|
|
53
|
-
def get_logger(logger_name: Optional[str] = None) -> logging.Logger:
|
|
59
|
+
def get_logger(logger_name: Optional[str] = None, control_level_in_runtime: bool = True) -> logging.Logger:
|
|
54
60
|
new_logger = logging.getLogger(logger_name)
|
|
55
61
|
new_logger.setLevel(get_logger_level())
|
|
56
62
|
|
|
57
|
-
_CREATED_LOGGERS.add(new_logger)
|
|
63
|
+
_CREATED_LOGGERS.add(CreatedLogger(logger=new_logger, control_level_in_runtime=control_level_in_runtime))
|
|
58
64
|
|
|
59
65
|
return new_logger
|
|
60
66
|
|
|
61
67
|
|
|
62
68
|
def set_logging_level(level: int) -> None:
|
|
63
69
|
for created_logger in _CREATED_LOGGERS:
|
|
64
|
-
created_logger.
|
|
70
|
+
if created_logger.control_level_in_runtime:
|
|
71
|
+
created_logger.logger.setLevel(level)
|
|
65
72
|
|
|
66
73
|
|
|
67
74
|
def get_val_as_string(key: str) -> str:
|
|
@@ -83,10 +90,9 @@ def get_val_as_int(key: str) -> Optional[int]:
|
|
|
83
90
|
|
|
84
91
|
def is_valid_url(url: str) -> bool:
|
|
85
92
|
try:
|
|
86
|
-
urlparse(url)
|
|
87
|
-
return
|
|
88
|
-
except ValueError
|
|
89
|
-
logger.warning(f'Invalid cycode api url: {url}, using default value', e)
|
|
93
|
+
parsed_url = urlparse(url)
|
|
94
|
+
return all([parsed_url.scheme, parsed_url.netloc])
|
|
95
|
+
except ValueError:
|
|
90
96
|
return False
|
|
91
97
|
|
|
92
98
|
|
|
@@ -95,6 +101,9 @@ configuration_manager = ConfigurationManager()
|
|
|
95
101
|
|
|
96
102
|
cycode_api_url = configuration_manager.get_cycode_api_url()
|
|
97
103
|
if not is_valid_url(cycode_api_url):
|
|
104
|
+
logger.warning(
|
|
105
|
+
'Invalid Cycode API URL: %s, using default value (%s)', cycode_api_url, consts.DEFAULT_CYCODE_API_URL
|
|
106
|
+
)
|
|
98
107
|
cycode_api_url = consts.DEFAULT_CYCODE_API_URL
|
|
99
108
|
|
|
100
109
|
timeout = get_val_as_int(consts.CYCODE_CLI_REQUEST_TIMEOUT_ENV_VAR_NAME)
|
|
@@ -44,7 +44,10 @@ class CycodeClientBase:
|
|
|
44
44
|
**kwargs,
|
|
45
45
|
) -> Response:
|
|
46
46
|
url = self.build_full_url(self.api_url, endpoint)
|
|
47
|
-
logger.debug(
|
|
47
|
+
logger.debug(
|
|
48
|
+
'Executing request, %s',
|
|
49
|
+
{'method': method.upper(), 'url': url},
|
|
50
|
+
)
|
|
48
51
|
|
|
49
52
|
timeout = self.timeout
|
|
50
53
|
if 'timeout' in kwargs:
|
|
@@ -56,7 +59,10 @@ class CycodeClientBase:
|
|
|
56
59
|
response = request(method=method, url=url, timeout=timeout, headers=headers, **kwargs)
|
|
57
60
|
|
|
58
61
|
content = 'HIDDEN' if hide_response_content_log else response.text
|
|
59
|
-
logger.debug(
|
|
62
|
+
logger.debug(
|
|
63
|
+
'Receiving response, %s',
|
|
64
|
+
{'status_code': response.status_code, 'url': url, 'content': content},
|
|
65
|
+
)
|
|
60
66
|
|
|
61
67
|
response.raise_for_status()
|
|
62
68
|
return response
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "cycode"
|
|
3
|
-
version = "1.9.
|
|
3
|
+
version = "1.9.6.dev2" # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
|
|
4
4
|
description = "Boost security in your dev lifecycle via SAST, SCA, Secrets & IaC scanning."
|
|
5
5
|
keywords=["secret-scan", "cycode", "devops", "token", "secret", "security", "cycode", "code"]
|
|
6
6
|
authors = ["Cycode <support@cycode.com>"]
|
|
@@ -96,6 +96,7 @@ extend-select = [
|
|
|
96
96
|
"TCH",
|
|
97
97
|
"TID",
|
|
98
98
|
"YTT",
|
|
99
|
+
"G",
|
|
99
100
|
]
|
|
100
101
|
line-length = 120
|
|
101
102
|
target-version = "py37"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '1.9.5.dev5' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/path/path_command.py
RENAMED
|
File without changes
|
{cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/report/sbom/repository_url/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/pre_commit/pre_commit_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/commands/scan/repository/repository_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-1.9.5.dev5 → cycode-1.9.6.dev2}/cycode/cli/files_collector/iac/tf_content_generator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|