cycode 3.0.1.dev1__py3-none-any.whl → 3.0.2.dev1__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.
cycode/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = '3.0.1.dev1' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
1
+ __version__ = '3.0.2.dev1' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
@@ -15,7 +15,7 @@ from cycode.cli.config import configuration_manager
15
15
  from cycode.cli.console import console
16
16
  from cycode.cli.exceptions import custom_exceptions
17
17
  from cycode.cli.exceptions.handle_scan_errors import handle_scan_exception
18
- from cycode.cli.files_collector.excluder import exclude_irrelevant_documents_to_scan
18
+ from cycode.cli.files_collector.excluder import excluder
19
19
  from cycode.cli.files_collector.models.in_memory_zip import InMemoryZip
20
20
  from cycode.cli.files_collector.path_documents import get_relevant_documents
21
21
  from cycode.cli.files_collector.repository_documents import (
@@ -56,8 +56,8 @@ def scan_sca_pre_commit(ctx: typer.Context, repo_path: str) -> None:
56
56
  progress_bar_section=ScanProgressBarSection.PREPARE_LOCAL_FILES,
57
57
  repo_path=repo_path,
58
58
  )
59
- git_head_documents = exclude_irrelevant_documents_to_scan(scan_type, git_head_documents)
60
- pre_committed_documents = exclude_irrelevant_documents_to_scan(scan_type, pre_committed_documents)
59
+ git_head_documents = excluder.exclude_irrelevant_documents_to_scan(scan_type, git_head_documents)
60
+ pre_committed_documents = excluder.exclude_irrelevant_documents_to_scan(scan_type, pre_committed_documents)
61
61
  sca_code_scanner.perform_pre_hook_range_scan_actions(repo_path, git_head_documents, pre_committed_documents)
62
62
  scan_commit_range_documents(
63
63
  ctx,
@@ -77,8 +77,8 @@ def scan_sca_commit_range(ctx: typer.Context, path: str, commit_range: str) -> N
77
77
  from_commit_documents, to_commit_documents = get_commit_range_modified_documents(
78
78
  progress_bar, ScanProgressBarSection.PREPARE_LOCAL_FILES, path, from_commit_rev, to_commit_rev
79
79
  )
80
- from_commit_documents = exclude_irrelevant_documents_to_scan(scan_type, from_commit_documents)
81
- to_commit_documents = exclude_irrelevant_documents_to_scan(scan_type, to_commit_documents)
80
+ from_commit_documents = excluder.exclude_irrelevant_documents_to_scan(scan_type, from_commit_documents)
81
+ to_commit_documents = excluder.exclude_irrelevant_documents_to_scan(scan_type, to_commit_documents)
82
82
  sca_code_scanner.perform_pre_commit_range_scan_actions(
83
83
  path, from_commit_documents, from_commit_rev, to_commit_documents, to_commit_rev
84
84
  )
@@ -288,7 +288,7 @@ def scan_commit_range(
288
288
  {'path': path, 'commit_range': commit_range, 'commit_id': commit_id},
289
289
  )
290
290
 
291
- documents_to_scan.extend(exclude_irrelevant_documents_to_scan(scan_type, commit_documents_to_scan))
291
+ documents_to_scan.extend(excluder.exclude_irrelevant_documents_to_scan(scan_type, commit_documents_to_scan))
292
292
 
293
293
  logger.debug('List of commit ids to scan, %s', {'commit_ids': commit_ids_to_scan})
294
294
  logger.debug('Starting to scan commit range (it may take a few minutes)')
@@ -5,7 +5,7 @@ import typer
5
5
 
6
6
  from cycode.cli import consts
7
7
  from cycode.cli.apps.scan.code_scanner import get_scan_parameters, scan_documents, scan_sca_pre_commit
8
- from cycode.cli.files_collector.excluder import exclude_irrelevant_documents_to_scan
8
+ from cycode.cli.files_collector.excluder import excluder
9
9
  from cycode.cli.files_collector.repository_documents import (
10
10
  get_diff_file_content,
11
11
  get_diff_file_path,
@@ -45,5 +45,5 @@ def pre_commit_command(
45
45
  progress_bar.update(ScanProgressBarSection.PREPARE_LOCAL_FILES)
46
46
  documents_to_scan.append(Document(get_path_by_os(get_diff_file_path(file)), get_diff_file_content(file)))
47
47
 
48
- documents_to_scan = exclude_irrelevant_documents_to_scan(scan_type, documents_to_scan)
48
+ documents_to_scan = excluder.exclude_irrelevant_documents_to_scan(scan_type, documents_to_scan)
49
49
  scan_documents(ctx, documents_to_scan, get_scan_parameters(ctx), is_git_diff=True)
@@ -7,7 +7,7 @@ import typer
7
7
  from cycode.cli import consts
8
8
  from cycode.cli.apps.scan.code_scanner import get_scan_parameters, scan_documents
9
9
  from cycode.cli.exceptions.handle_scan_errors import handle_scan_exception
10
- from cycode.cli.files_collector.excluder import exclude_irrelevant_documents_to_scan
10
+ from cycode.cli.files_collector.excluder import excluder
11
11
  from cycode.cli.files_collector.repository_documents import get_git_repository_tree_file_entries
12
12
  from cycode.cli.files_collector.sca.sca_code_scanner import perform_pre_scan_documents_actions
13
13
  from cycode.cli.logger import logger
@@ -57,7 +57,7 @@ def repository_command(
57
57
  )
58
58
  )
59
59
 
60
- documents_to_scan = exclude_irrelevant_documents_to_scan(scan_type, documents_to_scan)
60
+ documents_to_scan = excluder.exclude_irrelevant_documents_to_scan(scan_type, documents_to_scan)
61
61
 
62
62
  perform_pre_scan_documents_actions(ctx, scan_type, documents_to_scan)
63
63
 
@@ -9,6 +9,7 @@ from cycode.cli.consts import (
9
9
  ISSUE_DETECTED_STATUS_CODE,
10
10
  NO_ISSUES_STATUS_CODE,
11
11
  )
12
+ from cycode.cli.files_collector.excluder import excluder
12
13
  from cycode.cli.utils import scan_utils
13
14
  from cycode.cli.utils.get_api_client import get_scan_cycode_client
14
15
  from cycode.cli.utils.sentry import add_breadcrumb
@@ -138,13 +139,19 @@ def scan_command(
138
139
 
139
140
  ctx.obj['show_secret'] = show_secret
140
141
  ctx.obj['soft_fail'] = soft_fail
141
- ctx.obj['client'] = get_scan_cycode_client(ctx)
142
142
  ctx.obj['scan_type'] = scan_type
143
143
  ctx.obj['sync'] = sync
144
144
  ctx.obj['severity_threshold'] = severity_threshold
145
145
  ctx.obj['monitor'] = monitor
146
146
  ctx.obj['report'] = report
147
147
 
148
+ scan_client = get_scan_cycode_client(ctx)
149
+ ctx.obj['client'] = scan_client
150
+
151
+ remote_scan_config = scan_client.get_scan_configuration_safe(scan_type)
152
+ if remote_scan_config:
153
+ excluder.apply_scan_config(str(scan_type), remote_scan_config)
154
+
148
155
  if export_type and export_file:
149
156
  console_printer = ctx.obj['console_printer']
150
157
  console_printer.enable_recording(export_type, export_file)
@@ -10,36 +10,12 @@ from cycode.logger import get_logger
10
10
  if TYPE_CHECKING:
11
11
  from cycode.cli.models import Document
12
12
  from cycode.cli.utils.progress_bar import BaseProgressBar, ProgressBarSection
13
+ from cycode.cyclient import models
13
14
 
14
15
 
15
16
  logger = get_logger('File Excluder')
16
17
 
17
18
 
18
- def exclude_irrelevant_files(
19
- progress_bar: 'BaseProgressBar', progress_bar_section: 'ProgressBarSection', scan_type: str, filenames: list[str]
20
- ) -> list[str]:
21
- relevant_files = []
22
- for filename in filenames:
23
- progress_bar.update(progress_bar_section)
24
- if _is_relevant_file_to_scan(scan_type, filename):
25
- relevant_files.append(filename)
26
-
27
- is_sub_path.cache_clear() # free up memory
28
-
29
- return relevant_files
30
-
31
-
32
- def exclude_irrelevant_documents_to_scan(scan_type: str, documents_to_scan: list['Document']) -> list['Document']:
33
- logger.debug('Excluding irrelevant documents to scan')
34
-
35
- relevant_documents = []
36
- for document in documents_to_scan:
37
- if _is_relevant_document_to_scan(scan_type, document.path, document.content):
38
- relevant_documents.append(document)
39
-
40
- return relevant_documents
41
-
42
-
43
19
  def _is_subpath_of_cycode_configuration_folder(filename: str) -> bool:
44
20
  return (
45
21
  is_sub_path(configuration_manager.global_config_file_manager.get_config_directory_path(), filename)
@@ -63,43 +39,6 @@ def _does_document_exceed_max_size_limit(content: str) -> bool:
63
39
  return get_content_size(content) > consts.FILE_MAX_SIZE_LIMIT_IN_BYTES
64
40
 
65
41
 
66
- def _is_relevant_file_to_scan(scan_type: str, filename: str) -> bool:
67
- if _is_subpath_of_cycode_configuration_folder(filename):
68
- logger.debug(
69
- 'The file is irrelevant because it is in the Cycode configuration directory, %s',
70
- {'filename': filename, 'configuration_directory': consts.CYCODE_CONFIGURATION_DIRECTORY},
71
- )
72
- return False
73
-
74
- if _is_path_configured_in_exclusions(scan_type, filename):
75
- logger.debug('The file is irrelevant because its path is in the ignore paths list, %s', {'filename': filename})
76
- return False
77
-
78
- if not _is_file_extension_supported(scan_type, filename):
79
- logger.debug(
80
- 'The file is irrelevant because its extension is not supported, %s',
81
- {'scan_type': scan_type, 'filename': filename},
82
- )
83
- return False
84
-
85
- if is_binary_file(filename):
86
- logger.debug('The file is irrelevant because it is a binary file, %s', {'filename': filename})
87
- return False
88
-
89
- if scan_type != consts.SCA_SCAN_TYPE and _does_file_exceed_max_size_limit(filename):
90
- logger.debug(
91
- 'The file is irrelevant because it has exceeded the maximum size limit, %s',
92
- {
93
- 'max_file_size': consts.FILE_MAX_SIZE_LIMIT_IN_BYTES,
94
- 'file_size': get_file_size(filename),
95
- 'filename': filename,
96
- },
97
- )
98
- return False
99
-
100
- return not (scan_type == consts.SCA_SCAN_TYPE and not _is_file_relevant_for_sca_scan(filename))
101
-
102
-
103
42
  def _is_file_relevant_for_sca_scan(filename: str) -> bool:
104
43
  if any(sca_excluded_path in filename for sca_excluded_path in consts.SCA_EXCLUDED_PATHS):
105
44
  logger.debug(
@@ -110,52 +49,126 @@ def _is_file_relevant_for_sca_scan(filename: str) -> bool:
110
49
  return True
111
50
 
112
51
 
113
- def _is_relevant_document_to_scan(scan_type: str, filename: str, content: str) -> bool:
114
- if _is_subpath_of_cycode_configuration_folder(filename):
115
- logger.debug(
116
- 'The document is irrelevant because it is in the Cycode configuration directory, %s',
117
- {'filename': filename, 'configuration_directory': consts.CYCODE_CONFIGURATION_DIRECTORY},
118
- )
119
- return False
120
-
121
- if _is_path_configured_in_exclusions(scan_type, filename):
122
- logger.debug(
123
- 'The document is irrelevant because its path is in the ignore paths list, %s', {'filename': filename}
124
- )
125
- return False
126
-
127
- if not _is_file_extension_supported(scan_type, filename):
128
- logger.debug(
129
- 'The document is irrelevant because its extension is not supported, %s',
130
- {'scan_type': scan_type, 'filename': filename},
131
- )
132
- return False
133
-
134
- if is_binary_content(content):
135
- logger.debug('The document is irrelevant because it is a binary file, %s', {'filename': filename})
136
- return False
137
-
138
- if scan_type != consts.SCA_SCAN_TYPE and _does_document_exceed_max_size_limit(content):
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
- )
147
- return False
148
-
149
- return True
150
-
151
-
152
- def _is_file_extension_supported(scan_type: str, filename: str) -> bool:
153
- filename = filename.lower()
154
-
155
- if scan_type == consts.IAC_SCAN_TYPE:
156
- return filename.endswith(consts.IAC_SCAN_SUPPORTED_FILES)
157
-
158
- if scan_type == consts.SCA_SCAN_TYPE:
159
- return filename.endswith(consts.SCA_CONFIGURATION_SCAN_SUPPORTED_FILES)
160
-
161
- return not filename.endswith(consts.SECRET_SCAN_FILE_EXTENSIONS_TO_IGNORE)
52
+ class Excluder:
53
+ def __init__(self) -> None:
54
+ self._scannable_extensions: dict[str, tuple[str, ...]] = {
55
+ consts.IAC_SCAN_TYPE: consts.IAC_SCAN_SUPPORTED_FILES,
56
+ consts.SCA_SCAN_TYPE: consts.SCA_CONFIGURATION_SCAN_SUPPORTED_FILES,
57
+ }
58
+ self._non_scannable_extensions: dict[str, tuple[str, ...]] = {
59
+ consts.SECRET_SCAN_TYPE: consts.SECRET_SCAN_FILE_EXTENSIONS_TO_IGNORE,
60
+ }
61
+
62
+ def apply_scan_config(self, scan_type: str, scan_config: 'models.ScanConfiguration') -> None:
63
+ if scan_config.scannable_extensions:
64
+ self._scannable_extensions[scan_type] = tuple(scan_config.scannable_extensions)
65
+
66
+ def _is_file_extension_supported(self, scan_type: str, filename: str) -> bool:
67
+ filename = filename.lower()
68
+
69
+ scannable_extensions = self._scannable_extensions.get(scan_type)
70
+ if scannable_extensions:
71
+ return filename.endswith(scannable_extensions)
72
+
73
+ non_scannable_extensions = self._non_scannable_extensions.get(scan_type)
74
+ if non_scannable_extensions:
75
+ return not filename.endswith(non_scannable_extensions)
76
+
77
+ return True
78
+
79
+ def _is_relevant_file_to_scan_common(self, scan_type: str, filename: str) -> bool:
80
+ if _is_subpath_of_cycode_configuration_folder(filename):
81
+ logger.debug(
82
+ 'The document is irrelevant because it is in the Cycode configuration directory, %s',
83
+ {'filename': filename, 'configuration_directory': consts.CYCODE_CONFIGURATION_DIRECTORY},
84
+ )
85
+ return False
86
+
87
+ if _is_path_configured_in_exclusions(scan_type, filename):
88
+ logger.debug(
89
+ 'The document is irrelevant because its path is in the ignore paths list, %s', {'filename': filename}
90
+ )
91
+ return False
92
+
93
+ if not self._is_file_extension_supported(scan_type, filename):
94
+ logger.debug(
95
+ 'The document is irrelevant because its extension is not supported, %s',
96
+ {'scan_type': scan_type, 'filename': filename},
97
+ )
98
+ return False
99
+
100
+ return True
101
+
102
+ def _is_relevant_file_to_scan(self, scan_type: str, filename: str) -> bool:
103
+ if not self._is_relevant_file_to_scan_common(scan_type, filename):
104
+ return False
105
+
106
+ if is_binary_file(filename):
107
+ logger.debug('The file is irrelevant because it is a binary file, %s', {'filename': filename})
108
+ return False
109
+
110
+ if scan_type != consts.SCA_SCAN_TYPE and _does_file_exceed_max_size_limit(filename):
111
+ logger.debug(
112
+ 'The file is irrelevant because it has exceeded the maximum size limit, %s',
113
+ {
114
+ 'max_file_size': consts.FILE_MAX_SIZE_LIMIT_IN_BYTES,
115
+ 'file_size': get_file_size(filename),
116
+ 'filename': filename,
117
+ },
118
+ )
119
+ return False
120
+
121
+ return not (scan_type == consts.SCA_SCAN_TYPE and not _is_file_relevant_for_sca_scan(filename))
122
+
123
+ def _is_relevant_document_to_scan(self, scan_type: str, filename: str, content: str) -> bool:
124
+ if not self._is_relevant_file_to_scan_common(scan_type, filename):
125
+ return False
126
+
127
+ if is_binary_content(content):
128
+ logger.debug('The document is irrelevant because it is a binary file, %s', {'filename': filename})
129
+ return False
130
+
131
+ if scan_type != consts.SCA_SCAN_TYPE and _does_document_exceed_max_size_limit(content):
132
+ logger.debug(
133
+ 'The document is irrelevant because it has exceeded the maximum size limit, %s',
134
+ {
135
+ 'max_document_size': consts.FILE_MAX_SIZE_LIMIT_IN_BYTES,
136
+ 'document_size': get_content_size(content),
137
+ 'filename': filename,
138
+ },
139
+ )
140
+ return False
141
+
142
+ return True
143
+
144
+ def exclude_irrelevant_files(
145
+ self,
146
+ progress_bar: 'BaseProgressBar',
147
+ progress_bar_section: 'ProgressBarSection',
148
+ scan_type: str,
149
+ filenames: list[str],
150
+ ) -> list[str]:
151
+ relevant_files = []
152
+ for filename in filenames:
153
+ progress_bar.update(progress_bar_section)
154
+ if self._is_relevant_file_to_scan(scan_type, filename):
155
+ relevant_files.append(filename)
156
+
157
+ is_sub_path.cache_clear() # free up memory
158
+
159
+ return relevant_files
160
+
161
+ def exclude_irrelevant_documents_to_scan(
162
+ self, scan_type: str, documents_to_scan: list['Document']
163
+ ) -> list['Document']:
164
+ logger.debug('Excluding irrelevant documents to scan')
165
+
166
+ relevant_documents = []
167
+ for document in documents_to_scan:
168
+ if self._is_relevant_document_to_scan(scan_type, document.path, document.content):
169
+ relevant_documents.append(document)
170
+
171
+ return relevant_documents
172
+
173
+
174
+ excluder = Excluder()
@@ -1,25 +1,28 @@
1
+ from collections import defaultdict
1
2
  from io import BytesIO
3
+ from pathlib import Path
2
4
  from sys import getsizeof
3
- from typing import TYPE_CHECKING, Optional
5
+ from typing import Optional
4
6
  from zipfile import ZIP_DEFLATED, ZipFile
5
7
 
6
8
  from cycode.cli.user_settings.configuration_manager import ConfigurationManager
7
9
  from cycode.cli.utils.path_utils import concat_unique_id
8
10
 
9
- if TYPE_CHECKING:
10
- from pathlib import Path
11
-
12
11
 
13
12
  class InMemoryZip:
14
13
  def __init__(self) -> None:
15
14
  self.configuration_manager = ConfigurationManager()
16
15
 
17
- # Create the in-memory file-like object
18
16
  self.in_memory_zip = BytesIO()
19
- self.zip = ZipFile(self.in_memory_zip, 'a', ZIP_DEFLATED, False)
17
+ self.zip = ZipFile(self.in_memory_zip, mode='a', compression=ZIP_DEFLATED, allowZip64=False)
18
+
19
+ self._files_count = 0
20
+ self._extension_statistics = defaultdict(int)
20
21
 
21
22
  def append(self, filename: str, unique_id: Optional[str], content: str) -> None:
22
- # Write the file to the in-memory zip
23
+ self._files_count += 1
24
+ self._extension_statistics[Path(filename).suffix] += 1
25
+
23
26
  if unique_id:
24
27
  filename = concat_unique_id(filename, unique_id)
25
28
 
@@ -28,7 +31,6 @@ class InMemoryZip:
28
31
  def close(self) -> None:
29
32
  self.zip.close()
30
33
 
31
- # to bytes
32
34
  def read(self) -> bytes:
33
35
  self.in_memory_zip.seek(0)
34
36
  return self.in_memory_zip.read()
@@ -40,3 +42,11 @@ class InMemoryZip:
40
42
  @property
41
43
  def size(self) -> int:
42
44
  return getsizeof(self.in_memory_zip)
45
+
46
+ @property
47
+ def files_count(self) -> int:
48
+ return self._files_count
49
+
50
+ @property
51
+ def extension_statistics(self) -> dict[str, int]:
52
+ return dict(self._extension_statistics)
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  from typing import TYPE_CHECKING
3
3
 
4
- from cycode.cli.files_collector.excluder import exclude_irrelevant_files
4
+ from cycode.cli.files_collector.excluder import excluder
5
5
  from cycode.cli.files_collector.iac.tf_content_generator import (
6
6
  generate_tf_content_from_tfplan,
7
7
  generate_tfplan_document_name,
@@ -54,7 +54,9 @@ def _get_relevant_files(
54
54
  progress_bar_section_len = len(all_files_to_scan) * 2
55
55
  progress_bar.set_section_length(progress_bar_section, progress_bar_section_len)
56
56
 
57
- relevant_files_to_scan = exclude_irrelevant_files(progress_bar, progress_bar_section, scan_type, all_files_to_scan)
57
+ relevant_files_to_scan = excluder.exclude_irrelevant_files(
58
+ progress_bar, progress_bar_section, scan_type, all_files_to_scan
59
+ )
58
60
 
59
61
  # after finishing the first processing (excluding),
60
62
  # we must update the progress bar stage with respect of excluded files.
cycode/cyclient/models.py CHANGED
@@ -500,3 +500,19 @@ class SupportedModulesPreferencesSchema(Schema):
500
500
  @post_load
501
501
  def build_dto(self, data: dict[str, Any], **_) -> 'SupportedModulesPreferences':
502
502
  return SupportedModulesPreferences(**data)
503
+
504
+
505
+ @dataclass
506
+ class ScanConfiguration:
507
+ scannable_extensions: list[str]
508
+
509
+
510
+ class ScanConfigurationSchema(Schema):
511
+ class Meta:
512
+ unknown = EXCLUDE
513
+
514
+ scannable_extensions = fields.List(fields.String(), allow_none=True)
515
+
516
+ @post_load
517
+ def build_dto(self, data: dict[str, Any], **_) -> 'ScanConfiguration':
518
+ return ScanConfiguration(**data)
@@ -1,16 +1,17 @@
1
1
  import json
2
2
  from copy import deepcopy
3
- from typing import TYPE_CHECKING, Union
3
+ from typing import TYPE_CHECKING, Optional, Union
4
4
  from uuid import UUID
5
5
 
6
6
  from requests import Response
7
7
 
8
8
  from cycode.cli import consts
9
9
  from cycode.cli.config import configuration_manager
10
- from cycode.cli.exceptions.custom_exceptions import CycodeError
10
+ from cycode.cli.exceptions.custom_exceptions import CycodeError, RequestHttpError
11
11
  from cycode.cli.files_collector.models.in_memory_zip import InMemoryZip
12
12
  from cycode.cyclient import models
13
13
  from cycode.cyclient.cycode_client_base import CycodeClientBase
14
+ from cycode.cyclient.logger import logger
14
15
 
15
16
  if TYPE_CHECKING:
16
17
  from cycode.cyclient.scan_config_base import ScanConfigBase
@@ -100,12 +101,19 @@ class ScanClient:
100
101
  is_commit_range: bool = False,
101
102
  ) -> models.ScanInitializationResponse:
102
103
  files = {'file': ('multiple_files_scan.zip', zip_file.read())}
104
+
105
+ compression_manifest = {
106
+ 'file_count_by_extension': zip_file.extension_statistics,
107
+ 'file_count': zip_file.files_count,
108
+ }
109
+
103
110
  response = self.scan_cycode_client.post(
104
111
  url_path=self.get_zipped_file_scan_async_url_path(scan_type),
105
112
  data={
106
113
  'is_git_diff': is_git_diff,
107
114
  'scan_parameters': json.dumps(scan_parameters),
108
115
  'is_commit_range': is_commit_range,
116
+ 'compression_manifest': json.dumps(compression_manifest),
109
117
  },
110
118
  files=files,
111
119
  )
@@ -245,3 +253,25 @@ class ScanClient:
245
253
  @staticmethod
246
254
  def parse_scan_response(response: Response) -> models.ScanResult:
247
255
  return models.ScanResultSchema().load(response.json())
256
+
257
+ def get_scan_configuration_path(self, scan_type: str) -> str:
258
+ correct_scan_type = self.scan_config.get_async_scan_type(scan_type)
259
+ return f'{self.get_scan_service_url_path(scan_type)}/{correct_scan_type}/configuration'
260
+
261
+ def get_scan_configuration(self, scan_type: str) -> models.ScanConfiguration:
262
+ response = self.scan_cycode_client.get(
263
+ url_path=self.get_scan_configuration_path(scan_type),
264
+ hide_response_content_log=self._hide_response_log,
265
+ )
266
+ return models.ScanConfigurationSchema().load(response.json())
267
+
268
+ def get_scan_configuration_safe(self, scan_type: str) -> Optional['models.ScanConfiguration']:
269
+ try:
270
+ return self.get_scan_configuration(scan_type)
271
+ except RequestHttpError as e:
272
+ if e.status_code == 404:
273
+ logger.debug(
274
+ 'Remote scan configuration is not supported for this scan type: %s', {'scan_type': scan_type}
275
+ )
276
+ else:
277
+ logger.debug('Failed to get remote scan configuration: %s', {'scan_type': scan_type}, exc_info=e)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cycode
3
- Version: 3.0.1.dev1
3
+ Version: 3.0.2.dev1
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
@@ -1,4 +1,4 @@
1
- cycode/__init__.py,sha256=Rn-_mRmMpr1kmCEc2xv8Lbma0YXvsXvjtGPTevpnMd0,114
1
+ cycode/__init__.py,sha256=HzvkJQi7xG2wrtmqkbTnbxcwxUyzZlI37GX0h9LyzvU,114
2
2
  cycode/__main__.py,sha256=Z3bD5yrA7yPvAChcADQrqCaZd0ChGI1gdiwALwbWJ6U,104
3
3
  cycode/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  cycode/cli/app.py,sha256=VOWHpvF7PxLnxesElorhddn7EUWxe1NuJkljlrA9DbM,5958
@@ -30,21 +30,21 @@ cycode/cli/apps/report/sbom/repository_url/repository_url_command.py,sha256=VO4j
30
30
  cycode/cli/apps/report/sbom/sbom_command.py,sha256=bykQnmO0CCNInkih6bGmCcq5HFH-ItkFHPoxz683HCc,2229
31
31
  cycode/cli/apps/report/sbom/sbom_report_file.py,sha256=uyaJRvmg1K4DvJaMppbCf6yCj6UU-NdvNg-ZVZk0jx4,1576
32
32
  cycode/cli/apps/scan/__init__.py,sha256=FIEoPxBDIZ4MTabTxF7f8jlbXzABeKARcK6ATpjvmkI,1972
33
- cycode/cli/apps/scan/code_scanner.py,sha256=7jUxx7LQ6Rrkw_8rUl_377uliuE1sC2OKZwb-VoFp3Q,42340
33
+ cycode/cli/apps/scan/code_scanner.py,sha256=vUC5TfOCD0LNAFiajFrI6ZKCASgzYXZzbprEysF49dc,42357
34
34
  cycode/cli/apps/scan/commit_history/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
35
  cycode/cli/apps/scan/commit_history/commit_history_command.py,sha256=nWixiPJra3A9J7ddec3fnPx1GZFx7zNjHcsRHkx-IZU,1091
36
36
  cycode/cli/apps/scan/path/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
37
  cycode/cli/apps/scan/path/path_command.py,sha256=7M8nnohjB4SaNA7jv3mFODyX1wwwSmROe45e7E5GLbY,670
38
38
  cycode/cli/apps/scan/pre_commit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- cycode/cli/apps/scan/pre_commit/pre_commit_command.py,sha256=CjGgswGQFnREFaCTX3y3_GkBnfuRuQ0QP97uqA1OHFk,1766
39
+ cycode/cli/apps/scan/pre_commit/pre_commit_command.py,sha256=k-Bnf5pxX0oiseTPxLelSSnRclaJLb_jPZOrZSE7Ouw,1747
40
40
  cycode/cli/apps/scan/pre_receive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
41
  cycode/cli/apps/scan/pre_receive/pre_receive_command.py,sha256=6423KKB5H1TC9U4EuOe5NTDvbrQ4AP5I93-_DDa3Ztc,2687
42
42
  cycode/cli/apps/scan/repository/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
- cycode/cli/apps/scan/repository/repository_command.py,sha256=8YL1bF7ZmgqrX3UJMxjJoGE3YeqCHgeIwuiMec3ZO1g,2868
43
+ cycode/cli/apps/scan/repository/repository_command.py,sha256=Yt5izE8Aoym834dCtUJlfRl_64EaSt6BPZw_2D7eazM,2849
44
44
  cycode/cli/apps/scan/scan_ci/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
45
  cycode/cli/apps/scan/scan_ci/ci_integrations.py,sha256=3ZUv1uLsHC13KTNQ4erQKKDXAkmaSm5jow2Utwr4mCw,1634
46
46
  cycode/cli/apps/scan/scan_ci/scan_ci_command.py,sha256=RCU1ZHeGb97f_xLWrEPOKiry9U4WhNqvSURMRLNoK78,625
47
- cycode/cli/apps/scan/scan_command.py,sha256=SWF_lE1C3LxlP1mhpIlT2_soOwxGp3GZuPR6WLF32lI,6320
47
+ cycode/cli/apps/scan/scan_command.py,sha256=yn7k2LqUUYqV7xhhcK1hIHedcQRsVjh7fwW_-Qpm7Eo,6583
48
48
  cycode/cli/apps/status/__init__.py,sha256=uxfkEBafO7Da0mPc1fZhwoO0RTtyXp2a5T3LJTZxubU,371
49
49
  cycode/cli/apps/status/get_cli_status.py,sha256=qAuDdtWTCMI8ChYrQzgeJI31v8dDu-aEirMN8rThafk,2166
50
50
  cycode/cli/apps/status/models.py,sha256=2SBpJlh_MNCPxv8aXMV5D4GfK6-G-XB0GlMFZ3Nep_o,1907
@@ -62,12 +62,12 @@ cycode/cli/exceptions/handle_errors.py,sha256=9ZiDbHswXLe0TscUqZL9Or5Jq2AlYtzGb6
62
62
  cycode/cli/exceptions/handle_report_sbom_errors.py,sha256=bi0EizHtQLL-ovhHRH98CZ7qXdDPLTYnI59Jn1Y5c0E,926
63
63
  cycode/cli/exceptions/handle_scan_errors.py,sha256=-QIYvbBXmZVOvAdNwGYwAdmBma6Z_pPpS0a77aDICp8,1916
64
64
  cycode/cli/files_collector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
- cycode/cli/files_collector/excluder.py,sha256=OhFPCOvJpQpvKUchcw-ACb0Dz0xrS4_GZnKL7YgWOo8,6217
65
+ cycode/cli/files_collector/excluder.py,sha256=Qf6N2Wrhu4jrUMFAN70nc8tvxPBEMAT33TeSi_wKzFY,6904
66
66
  cycode/cli/files_collector/iac/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
67
  cycode/cli/files_collector/iac/tf_content_generator.py,sha256=a65zA0Ejv_LSA5jac2omHck4IKoNS5MX6v6ltF2wo4E,2873
68
68
  cycode/cli/files_collector/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
- cycode/cli/files_collector/models/in_memory_zip.py,sha256=xVyW3lJkx85-Zz7s98X1Ks9mfBIdKg06KLd2idjlY-0,1239
70
- cycode/cli/files_collector/path_documents.py,sha256=ufXHEjXKITs8fJm2rYQtYYV9A4z8VGJzrr0YLwkM6X4,4199
69
+ cycode/cli/files_collector/models/in_memory_zip.py,sha256=w1bR2WBUR-WLzJMvTeaSMJSGtEC1zRgJUfbnlGyl7Jk,1535
70
+ cycode/cli/files_collector/path_documents.py,sha256=AeCJ2guMIQ13P9JsaLKIyxzqtIH3lvsegqbwwZtl85I,4206
71
71
  cycode/cli/files_collector/repository_documents.py,sha256=f1Mk7Zr3tEDfxy55RaFyHryiZy17leOJ95Kz5hMF2fE,5151
72
72
  cycode/cli/files_collector/sca/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
73
  cycode/cli/files_collector/sca/base_restore_dependencies.py,sha256=jbP0SZRgpu8KehxyiGkD988k-Fysqmc1Lyn9y7tjuTo,3377
@@ -143,13 +143,13 @@ cycode/cyclient/cycode_dev_based_client.py,sha256=8LxeUWizXzZ0ilpwb6Q0W4ZMLZyZdK
143
143
  cycode/cyclient/cycode_token_based_client.py,sha256=tD_HWgkz0VDcU4AQsPxHxGTwfQ8KlpXGHNbyfRxu2jk,3779
144
144
  cycode/cyclient/headers.py,sha256=5aLezpRDBzueH9T1hB_6VyUydRpTs3rN17CDDPn1BxI,1448
145
145
  cycode/cyclient/logger.py,sha256=oTkay7QzoOIVQ71cGOy4ukkijYGA3IKJlHkL24Px5ds,70
146
- cycode/cyclient/models.py,sha256=YUQasr_hVTk5kJpktkFNXJvv6q5bOEshyM75IJTHRH8,13813
146
+ cycode/cyclient/models.py,sha256=gGZhqbcjf49eV2n0nXG92DkFhluYfwF1uRp1yXRfDYU,14176
147
147
  cycode/cyclient/report_client.py,sha256=h12pz3vWCwDF73BhqFX7iDSxBgQDFwkiGh3hmul2nsM,3965
148
- cycode/cyclient/scan_client.py,sha256=51Q5eSj6y8n7e4FpYaS-DOU6kz0Gr9-ni451EpMXVok,10380
148
+ cycode/cyclient/scan_client.py,sha256=cKXBqJcwf97yw9PkswN5fgGx4Brp2l6P6zb8SROVvcE,11806
149
149
  cycode/cyclient/scan_config_base.py,sha256=mXsPZGYCtp85rv5GIige40yQZXuRcEKUW-VQJ0vgFzk,1201
150
150
  cycode/logger.py,sha256=tKiTDKIVbE7pQiXxMBDsT1SP3PWaNZ-yzSMkbbkomxk,1972
151
- cycode-3.0.1.dev1.dist-info/LICENCE,sha256=2Wx4N6mD_4xB7-E3hPkZ3MPhpJy__k_I8MaCSO-PDRo,1068
152
- cycode-3.0.1.dev1.dist-info/METADATA,sha256=R-k6-bFHktIXz0QctPZJBUzkjoPreLkUpMOHr60rVbc,46217
153
- cycode-3.0.1.dev1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
154
- cycode-3.0.1.dev1.dist-info/entry_points.txt,sha256=iDcVJM8ByLElVgvBgtYxDjw1kT7O8Mo0LcWZIT5L3Ig,45
155
- cycode-3.0.1.dev1.dist-info/RECORD,,
151
+ cycode-3.0.2.dev1.dist-info/LICENCE,sha256=2Wx4N6mD_4xB7-E3hPkZ3MPhpJy__k_I8MaCSO-PDRo,1068
152
+ cycode-3.0.2.dev1.dist-info/METADATA,sha256=c4VwvMuhFBXNVc5Ke3N5iHaTFQubHGF5Fon3PQZygu4,46217
153
+ cycode-3.0.2.dev1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
154
+ cycode-3.0.2.dev1.dist-info/entry_points.txt,sha256=iDcVJM8ByLElVgvBgtYxDjw1kT7O8Mo0LcWZIT5L3Ig,45
155
+ cycode-3.0.2.dev1.dist-info/RECORD,,