cycode 0.2.5.dev6__tar.gz → 0.2.5.dev7__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.
Files changed (63) hide show
  1. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/PKG-INFO +7 -7
  2. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/README.md +6 -6
  3. cycode-0.2.5.dev7/cycode/__init__.py +1 -0
  4. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/main.py +4 -4
  5. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/printers/base_printer.py +3 -1
  6. cycode-0.2.5.dev7/cycode/cli/printers/base_table_printer.py +43 -0
  7. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/printers/console_printer.py +10 -6
  8. cycode-0.2.5.dev6/cycode/cli/printers/table_printer.py → cycode-0.2.5.dev7/cycode/cli/printers/sca_table_printer.py +4 -32
  9. cycode-0.2.5.dev7/cycode/cli/printers/table.py +61 -0
  10. cycode-0.2.5.dev7/cycode/cli/printers/table_models.py +20 -0
  11. cycode-0.2.5.dev7/cycode/cli/printers/table_printer.py +116 -0
  12. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/printers/text_printer.py +3 -10
  13. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/utils/string_utils.py +4 -0
  14. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/pyproject.toml +1 -1
  15. cycode-0.2.5.dev6/cycode/__init__.py +0 -1
  16. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/__init__.py +0 -0
  17. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/auth/__init__.py +0 -0
  18. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/auth/auth_command.py +0 -0
  19. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/auth/auth_manager.py +0 -0
  20. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/ci_integrations.py +0 -0
  21. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/code_scanner.py +0 -0
  22. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/config.py +0 -0
  23. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/config.yaml +0 -0
  24. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/consts.py +0 -0
  25. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/exceptions/__init__.py +0 -0
  26. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/exceptions/custom_exceptions.py +0 -0
  27. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/helpers/__init__.py +0 -0
  28. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/helpers/maven/__init__.py +0 -0
  29. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/helpers/maven/base_restore_maven_dependencies.py +0 -0
  30. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/helpers/maven/restore_gradle_dependencies.py +0 -0
  31. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/helpers/maven/restore_maven_dependencies.py +0 -0
  32. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/helpers/sca_code_scanner.py +0 -0
  33. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/models.py +0 -0
  34. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/printers/__init__.py +0 -0
  35. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/printers/json_printer.py +0 -0
  36. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/user_settings/__init__.py +0 -0
  37. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/user_settings/base_file_manager.py +0 -0
  38. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/user_settings/config_file_manager.py +0 -0
  39. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/user_settings/configuration_manager.py +0 -0
  40. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/user_settings/credentials_manager.py +0 -0
  41. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/user_settings/user_settings_commands.py +0 -0
  42. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/utils/__init__.py +0 -0
  43. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/utils/path_utils.py +0 -0
  44. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/utils/scan_utils.py +0 -0
  45. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/utils/shell_executor.py +0 -0
  46. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/utils/task_timer.py +0 -0
  47. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/utils/yaml_utils.py +0 -0
  48. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cli/zip_file.py +0 -0
  49. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/__init__.py +0 -0
  50. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/auth_client.py +0 -0
  51. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/config.py +0 -0
  52. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/config.yaml +0 -0
  53. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/config_dev.py +0 -0
  54. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/cycode_client.py +0 -0
  55. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/cycode_client_base.py +0 -0
  56. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/cycode_dev_based_client.py +0 -0
  57. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/cycode_token_based_client.py +0 -0
  58. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/models.py +0 -0
  59. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/scan_client.py +0 -0
  60. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/scan_config/__init__.py +0 -0
  61. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/scan_config/scan_config_base.py +0 -0
  62. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/scan_config/scan_config_creator.py +0 -0
  63. {cycode-0.2.5.dev6 → cycode-0.2.5.dev7}/cycode/cyclient/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cycode
3
- Version: 0.2.5.dev6
3
+ Version: 0.2.5.dev7
4
4
  Summary: Perform secrets/iac scans for your sources using Cycode's engine
5
5
  Home-page: https://github.com/cycodehq-public/cycode-cli
6
6
  License: MIT
@@ -248,12 +248,12 @@ repos:
248
248
 
249
249
  The following are the options and commands available with the Cycode CLI application:
250
250
 
251
- | Option | Description |
252
- |-------------------------|-----------------------------------------------------------|
253
- | `--output [text\|json]` | Specify the output (`text`/`json`). The default is `text` |
254
- | `-v`, `--verbose` | Show detailed logs |
255
- | `--version` | Show the version and exit. |
256
- | `--help` | Show options for given command. |
251
+ | Option | Description |
252
+ |--------------------------------|-------------------------------------------------------------------|
253
+ | `--output [text\|json\|table]` | Specify the output (`text`/`json`/`table`). The default is `text` |
254
+ | `-v`, `--verbose` | Show detailed logs |
255
+ | `--version` | Show the version and exit. |
256
+ | `--help` | Show options for given command. |
257
257
 
258
258
  | Command | Description |
259
259
  |-------------------------------------|-------------|
@@ -211,12 +211,12 @@ repos:
211
211
 
212
212
  The following are the options and commands available with the Cycode CLI application:
213
213
 
214
- | Option | Description |
215
- |-------------------------|-----------------------------------------------------------|
216
- | `--output [text\|json]` | Specify the output (`text`/`json`). The default is `text` |
217
- | `-v`, `--verbose` | Show detailed logs |
218
- | `--version` | Show the version and exit. |
219
- | `--help` | Show options for given command. |
214
+ | Option | Description |
215
+ |--------------------------------|-------------------------------------------------------------------|
216
+ | `--output [text\|json\|table]` | Specify the output (`text`/`json`/`table`). The default is `text` |
217
+ | `-v`, `--verbose` | Show detailed logs |
218
+ | `--version` | Show the version and exit. |
219
+ | `--help` | Show options for given command. |
220
220
 
221
221
  | Command | Description |
222
222
  |-------------------------------------|-------------|
@@ -0,0 +1 @@
1
+ __version__ = '0.2.5.dev7' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
@@ -65,10 +65,10 @@ NO_ISSUES_STATUS_CODE = 0
65
65
  @click.option('--output', default=None,
66
66
  help="""
67
67
  \b
68
- Specify the results output (text/json),
68
+ Specify the results output (text/json/table),
69
69
  the default is text
70
70
  """,
71
- type=click.Choice(['text', 'json']))
71
+ type=click.Choice(['text', 'json', 'table']))
72
72
  @click.option('--severity-threshold',
73
73
  default=None,
74
74
  help='Show only violations at the specified level or higher (supported for SCA scan type only).',
@@ -142,8 +142,8 @@ def finalize(context: click.Context, *args, **kwargs):
142
142
  @click.option(
143
143
  '--output',
144
144
  default='text',
145
- help='Specify the output (text/json), the default is text',
146
- type=click.Choice(['text', 'json'])
145
+ help='Specify the output (text/json/table), the default is text',
146
+ type=click.Choice(['text', 'json', 'table'])
147
147
  )
148
148
  @click.option(
149
149
  '--user-agent',
@@ -7,7 +7,9 @@ from cycode.cli.models import DocumentDetections, CliResult, CliError
7
7
 
8
8
 
9
9
  class BasePrinter(ABC):
10
- context: click.Context
10
+ RED_COLOR_NAME = 'red'
11
+ WHITE_COLOR_NAME = 'white'
12
+ GREEN_COLOR_NAME = 'green'
11
13
 
12
14
  def __init__(self, context: click.Context):
13
15
  self.context = context
@@ -0,0 +1,43 @@
1
+ import abc
2
+ from typing import List
3
+
4
+ import click
5
+
6
+ from cycode.cli.printers.text_printer import TextPrinter
7
+ from cycode.cli.models import DocumentDetections, CliError, CliResult
8
+ from cycode.cli.printers.base_printer import BasePrinter
9
+
10
+
11
+ class BaseTablePrinter(BasePrinter, abc.ABC):
12
+ def __init__(self, context: click.Context):
13
+ super().__init__(context)
14
+ self.context = context
15
+ self.scan_id: str = context.obj.get('scan_id')
16
+ self.scan_type: str = context.obj.get('scan_type')
17
+ self.show_secret: bool = context.obj.get('show_secret', False)
18
+
19
+ def print_result(self, result: CliResult) -> None:
20
+ TextPrinter(self.context).print_result(result)
21
+
22
+ def print_error(self, error: CliError) -> None:
23
+ TextPrinter(self.context).print_error(error)
24
+
25
+ def print_scan_results(self, results: List[DocumentDetections]):
26
+ click.secho(f'Scan Results: (scan_id: {self.scan_id})')
27
+
28
+ if not results:
29
+ click.secho('Good job! No issues were found!!! 👏👏👏', fg=self.GREEN_COLOR_NAME)
30
+ return
31
+
32
+ self._print_results(results)
33
+
34
+ report_url = self.context.obj.get('report_url')
35
+ if report_url:
36
+ click.secho(f'Report URL: {report_url}')
37
+
38
+ def _is_git_repository(self) -> bool:
39
+ return self.context.obj.get('remote_url') is not None
40
+
41
+ @abc.abstractmethod
42
+ def _print_results(self, results: List[DocumentDetections]) -> None:
43
+ raise NotImplementedError
@@ -1,10 +1,10 @@
1
1
  import click
2
2
  from typing import List, TYPE_CHECKING
3
3
 
4
- from cycode.cli.consts import SCA_SCAN_TYPE
5
4
  from cycode.cli.exceptions.custom_exceptions import CycodeError
6
5
  from cycode.cli.models import DocumentDetections, CliResult, CliError
7
6
  from cycode.cli.printers.table_printer import TablePrinter
7
+ from cycode.cli.printers.sca_table_printer import SCATablePrinter
8
8
  from cycode.cli.printers.json_printer import JsonPrinter
9
9
  from cycode.cli.printers.text_printer import TextPrinter
10
10
 
@@ -16,11 +16,15 @@ class ConsolePrinter:
16
16
  _AVAILABLE_PRINTERS = {
17
17
  'text': TextPrinter,
18
18
  'json': JsonPrinter,
19
- 'text_sca': TablePrinter
19
+ 'table': TablePrinter,
20
+ # overrides
21
+ 'table_sca': SCATablePrinter,
22
+ 'text_sca': SCATablePrinter,
20
23
  }
21
24
 
22
25
  def __init__(self, context: click.Context):
23
26
  self.context = context
27
+ self.scan_type = self.context.obj.get('scan_type')
24
28
  self.output_type = self.context.obj.get('output')
25
29
 
26
30
  self._printer_class = self._AVAILABLE_PRINTERS.get(self.output_type)
@@ -32,11 +36,11 @@ class ConsolePrinter:
32
36
  printer.print_scan_results(detections_results_list)
33
37
 
34
38
  def _get_scan_printer(self) -> 'BasePrinter':
35
- scan_type = self.context.obj.get('scan_type')
36
-
37
39
  printer_class = self._printer_class
38
- if scan_type == SCA_SCAN_TYPE and self.output_type == 'text':
39
- printer_class = TablePrinter
40
+
41
+ composite_printer = self._AVAILABLE_PRINTERS.get(f'{self.output_type}_{self.scan_type}')
42
+ if composite_printer:
43
+ printer_class = composite_printer
40
44
 
41
45
  return printer_class(self.context)
42
46
 
@@ -5,8 +5,8 @@ import click
5
5
  from texttable import Texttable
6
6
 
7
7
  from cycode.cli.consts import LICENSE_COMPLIANCE_POLICY_ID, PACKAGE_VULNERABILITY_POLICY_ID
8
- from cycode.cli.models import DocumentDetections, Detection, CliError, CliResult
9
- from cycode.cli.printers.base_printer import BasePrinter
8
+ from cycode.cli.models import DocumentDetections, Detection
9
+ from cycode.cli.printers.base_table_printer import BaseTablePrinter
10
10
 
11
11
  SEVERITY_COLUMN = 'Severity'
12
12
  LICENSE_COLUMN = 'License'
@@ -23,36 +23,11 @@ PREVIEW_DETECTIONS_COMMON_HEADERS = [
23
23
  ]
24
24
 
25
25
 
26
- class TablePrinter(BasePrinter):
27
- RED_COLOR_NAME = 'red'
28
- WHITE_COLOR_NAME = 'white'
29
- GREEN_COLOR_NAME = 'green'
30
-
31
- def __init__(self, context: click.Context):
32
- super().__init__(context)
33
- self.scan_id = context.obj.get('scan_id')
34
-
35
- def print_result(self, result: CliResult) -> None:
36
- raise NotImplemented
37
-
38
- def print_error(self, error: CliError) -> None:
39
- raise NotImplemented
40
-
41
- def print_scan_results(self, results: List[DocumentDetections]):
42
- click.secho(f"Scan Results: (scan_id: {self.scan_id})")
43
-
44
- if not results:
45
- click.secho("Good job! No issues were found!!! 👏👏👏", fg=self.GREEN_COLOR_NAME)
46
- return
47
-
26
+ class SCATablePrinter(BaseTablePrinter):
27
+ def _print_results(self, results: List[DocumentDetections]) -> None:
48
28
  detections_per_detection_type_id = self._extract_detections_per_detection_type_id(results)
49
-
50
29
  self._print_detection_per_detection_type_id(detections_per_detection_type_id)
51
30
 
52
- report_url = self.context.obj.get('report_url')
53
- if report_url:
54
- click.secho(f'Report URL: {report_url}')
55
-
56
31
  @staticmethod
57
32
  def _extract_detections_per_detection_type_id(results: List[DocumentDetections]) -> Dict[str, List[Detection]]:
58
33
  detections_per_detection_type_id = defaultdict(list)
@@ -146,9 +121,6 @@ class TablePrinter(BasePrinter):
146
121
 
147
122
  return row
148
123
 
149
- def _is_git_repository(self) -> bool:
150
- return self.context.obj.get("remote_url") is not None
151
-
152
124
  def _get_upgrade_package_vulnerability(self, detection: Detection) -> List[str]:
153
125
  alert = detection.detection_details.get('alert')
154
126
  row = [
@@ -0,0 +1,61 @@
1
+ from typing import List, Dict, Optional, TYPE_CHECKING
2
+ from texttable import Texttable
3
+
4
+ if TYPE_CHECKING:
5
+ from cycode.cli.printers.table_models import ColumnInfo, ColumnWidths
6
+
7
+
8
+ class Table:
9
+ """Helper class to manage columns and their values in the right order and only if the column should be presented."""
10
+
11
+ def __init__(self, column_infos: Optional[List['ColumnInfo']] = None):
12
+ self._column_widths = None
13
+
14
+ self._columns: Dict['ColumnInfo', List[str]] = dict()
15
+ if column_infos:
16
+ self._columns: Dict['ColumnInfo', List[str]] = {columns: list() for columns in column_infos}
17
+
18
+ def add(self, column: 'ColumnInfo') -> None:
19
+ self._columns[column] = list()
20
+
21
+ def set(self, column: 'ColumnInfo', value: str) -> None:
22
+ # we push values only for existing columns what were added before
23
+ if column in self._columns:
24
+ self._columns[column].append(value)
25
+
26
+ def _get_ordered_columns(self) -> List['ColumnInfo']:
27
+ # we are sorting columns by index to make sure that columns will be printed in the right order
28
+ return sorted(self._columns, key=lambda column_info: column_info.index)
29
+
30
+ def get_columns_info(self) -> List['ColumnInfo']:
31
+ return self._get_ordered_columns()
32
+
33
+ def get_headers(self) -> List[str]:
34
+ return [header.name for header in self._get_ordered_columns()]
35
+
36
+ def get_rows(self) -> List[str]:
37
+ column_values = [self._columns[column_info] for column_info in self._get_ordered_columns()]
38
+ return list(zip(*column_values))
39
+
40
+ def set_cols_width(self, column_widths: 'ColumnWidths') -> None:
41
+ header_width_size = []
42
+ for header in self.get_columns_info():
43
+ width_multiplier = 1
44
+ if header in column_widths:
45
+ width_multiplier = column_widths[header]
46
+
47
+ header_width_size.append(len(header.name) * width_multiplier)
48
+
49
+ self._column_widths = header_width_size
50
+
51
+ def get_table(self, max_width: int = 80) -> Texttable:
52
+ table = Texttable(max_width)
53
+ table.header(self.get_headers())
54
+
55
+ for row in self.get_rows():
56
+ table.add_row(row)
57
+
58
+ if self._column_widths:
59
+ table.set_cols_width(self._column_widths)
60
+
61
+ return table
@@ -0,0 +1,20 @@
1
+ from typing import NamedTuple, Dict
2
+
3
+
4
+ class ColumnInfoBuilder:
5
+ _index = 0
6
+
7
+ @staticmethod
8
+ def build(name: str) -> 'ColumnInfo':
9
+ column_info = ColumnInfo(name, ColumnInfoBuilder._index)
10
+ ColumnInfoBuilder._index += 1
11
+ return column_info
12
+
13
+
14
+ class ColumnInfo(NamedTuple):
15
+ name: str
16
+ index: int # Represents the order of the columns, starting from the left
17
+
18
+
19
+ ColumnWidths = Dict[ColumnInfo, int]
20
+ ColumnWidthsConfig = Dict[str, ColumnWidths]
@@ -0,0 +1,116 @@
1
+ from typing import List
2
+
3
+ import click
4
+
5
+ from cycode.cli.printers.base_table_printer import BaseTablePrinter
6
+ from cycode.cli.printers.table_models import ColumnInfoBuilder, ColumnWidthsConfig
7
+ from cycode.cli.printers.table import Table
8
+ from cycode.cli.utils.string_utils import obfuscate_text, get_position_in_line
9
+ from cycode.cli.consts import SECRET_SCAN_TYPE, INFRA_CONFIGURATION_SCAN_TYPE, SAST_SCAN_TYPE
10
+ from cycode.cli.models import DocumentDetections, Detection, Document
11
+
12
+ # Creation must have strict order. Represents the order of the columns in the table (from left to right)
13
+ ISSUE_TYPE_COLUMN = ColumnInfoBuilder.build(name='Issue Type')
14
+ RULE_ID_COLUMN = ColumnInfoBuilder.build(name='Rule ID')
15
+ FILE_PATH_COLUMN = ColumnInfoBuilder.build(name='File Path')
16
+ SECRET_SHA_COLUMN = ColumnInfoBuilder.build(name='Secret SHA')
17
+ COMMIT_SHA_COLUMN = ColumnInfoBuilder.build(name='Commit SHA')
18
+ LINE_NUMBER_COLUMN = ColumnInfoBuilder.build(name='Line Number')
19
+ COLUMN_NUMBER_COLUMN = ColumnInfoBuilder.build(name='Column Number')
20
+ VIOLATION_LENGTH_COLUMN = ColumnInfoBuilder.build(name='Violation Length')
21
+ VIOLATION_COLUMN = ColumnInfoBuilder.build(name='Violation')
22
+
23
+ COLUMN_WIDTHS_CONFIG: ColumnWidthsConfig = {
24
+ SECRET_SCAN_TYPE: {
25
+ ISSUE_TYPE_COLUMN: 2,
26
+ RULE_ID_COLUMN: 2,
27
+ FILE_PATH_COLUMN: 2,
28
+ SECRET_SHA_COLUMN: 2,
29
+ VIOLATION_COLUMN: 2,
30
+ },
31
+ INFRA_CONFIGURATION_SCAN_TYPE: {
32
+ ISSUE_TYPE_COLUMN: 4,
33
+ RULE_ID_COLUMN: 3,
34
+ FILE_PATH_COLUMN: 3,
35
+ },
36
+ SAST_SCAN_TYPE: {
37
+ ISSUE_TYPE_COLUMN: 7,
38
+ RULE_ID_COLUMN: 2,
39
+ FILE_PATH_COLUMN: 3,
40
+ },
41
+ }
42
+
43
+
44
+ class TablePrinter(BaseTablePrinter):
45
+ def _print_results(self, results: List[DocumentDetections]) -> None:
46
+ table = self._get_table()
47
+ if self.scan_type in COLUMN_WIDTHS_CONFIG:
48
+ table.set_cols_width(COLUMN_WIDTHS_CONFIG[self.scan_type])
49
+
50
+ for result in results:
51
+ for detection in result.detections:
52
+ self._enrich_table_with_values(table, detection, result.document)
53
+
54
+ click.echo(table.get_table().draw())
55
+
56
+ def _get_table(self) -> Table:
57
+ table = Table()
58
+
59
+ table.add(ISSUE_TYPE_COLUMN)
60
+ table.add(RULE_ID_COLUMN)
61
+ table.add(FILE_PATH_COLUMN)
62
+ table.add(LINE_NUMBER_COLUMN)
63
+ table.add(COLUMN_NUMBER_COLUMN)
64
+
65
+ if self._is_git_repository():
66
+ table.add(COMMIT_SHA_COLUMN)
67
+
68
+ if self.scan_type == SECRET_SCAN_TYPE:
69
+ table.add(SECRET_SHA_COLUMN)
70
+ table.add(VIOLATION_LENGTH_COLUMN)
71
+ table.add(VIOLATION_COLUMN)
72
+
73
+ return table
74
+
75
+ def _enrich_table_with_values(self, table: Table, detection: Detection, document: Document) -> None:
76
+ self._enrich_table_with_detection_summary_values(table, detection, document)
77
+ self._enrich_table_with_detection_code_segment_values(table, detection, document)
78
+
79
+ def _enrich_table_with_detection_summary_values(
80
+ self, table: Table, detection: Detection, document: Document
81
+ ) -> None:
82
+ issue_type = detection.message
83
+ if self.scan_type == SECRET_SCAN_TYPE:
84
+ issue_type = detection.type
85
+
86
+ table.set(ISSUE_TYPE_COLUMN, issue_type)
87
+ table.set(RULE_ID_COLUMN, detection.detection_rule_id)
88
+ table.set(FILE_PATH_COLUMN, click.format_filename(document.path))
89
+ table.set(SECRET_SHA_COLUMN, detection.detection_details.get('sha512', ''))
90
+ table.set(COMMIT_SHA_COLUMN, detection.detection_details.get('commit_id', ''))
91
+
92
+ def _enrich_table_with_detection_code_segment_values(
93
+ self, table: Table, detection: Detection, document: Document
94
+ ) -> None:
95
+ detection_details = detection.detection_details
96
+
97
+ detection_line = detection_details.get('line_in_file', -1)
98
+ if self.scan_type == SECRET_SCAN_TYPE:
99
+ detection_line = detection_details.get('line', -1)
100
+
101
+ detection_column = get_position_in_line(document.content, detection_details.get('start_position', -1))
102
+ violation_length = detection_details.get('length', -1)
103
+
104
+ violation = ''
105
+ file_content_lines = document.content.splitlines()
106
+ if detection_line < len(file_content_lines):
107
+ line = file_content_lines[detection_line]
108
+ violation = line[detection_column: detection_column + violation_length]
109
+
110
+ if not self.show_secret:
111
+ violation = obfuscate_text(violation)
112
+
113
+ table.set(LINE_NUMBER_COLUMN, str(detection_line))
114
+ table.set(COLUMN_NUMBER_COLUMN, str(detection_column))
115
+ table.set(VIOLATION_LENGTH_COLUMN, f'{violation_length} chars')
116
+ table.set(VIOLATION_COLUMN, violation)
@@ -7,14 +7,10 @@ from cycode.cli.printers.base_printer import BasePrinter
7
7
  from cycode.cli.models import DocumentDetections, Detection, Document, CliResult, CliError
8
8
  from cycode.cli.config import config
9
9
  from cycode.cli.consts import SECRET_SCAN_TYPE, COMMIT_RANGE_BASED_COMMAND_SCAN_TYPES
10
- from cycode.cli.utils.string_utils import obfuscate_text
10
+ from cycode.cli.utils.string_utils import obfuscate_text, get_position_in_line
11
11
 
12
12
 
13
13
  class TextPrinter(BasePrinter):
14
- RED_COLOR_NAME = 'red'
15
- WHITE_COLOR_NAME = 'white'
16
- GREEN_COLOR_NAME = 'green'
17
-
18
14
  def __init__(self, context: click.Context):
19
15
  super().__init__(context)
20
16
  self.scan_id: str = context.obj.get('scan_id')
@@ -132,9 +128,6 @@ class TextPrinter(BasePrinter):
132
128
 
133
129
  return self.WHITE_COLOR_NAME
134
130
 
135
- def _get_position_in_line(self, text: str, position: int) -> int:
136
- return position - text.rfind('\n', 0, position) - 1
137
-
138
131
  def _get_line_number_style(self, line_number: int):
139
132
  return f'{click.style(str(line_number), fg=self.WHITE_COLOR_NAME, bold=False)} ' \
140
133
  f'{click.style("|", fg=self.RED_COLOR_NAME, bold=False)}'
@@ -158,7 +151,7 @@ class TextPrinter(BasePrinter):
158
151
  file_content = document.content
159
152
  file_lines = file_content.splitlines()
160
153
  start_line = self._get_code_segment_start_line(detection_line, code_segment_size)
161
- detection_position_in_line = self._get_position_in_line(file_content, detection_position)
154
+ detection_position_in_line = get_position_in_line(file_content, detection_position)
162
155
 
163
156
  click.echo()
164
157
  for i in range(code_segment_size):
@@ -182,7 +175,7 @@ class TextPrinter(BasePrinter):
182
175
  git_diff_content = document.content
183
176
  git_diff_lines = git_diff_content.splitlines()
184
177
  detection_line = git_diff_lines[detection_line_number]
185
- detection_position_in_line = self._get_position_in_line(git_diff_content, detection_position)
178
+ detection_position_in_line = get_position_in_line(git_diff_content, detection_position)
186
179
 
187
180
  click.echo()
188
181
  self._print_detection_line(document, detection_line, detection_line_number_in_original_file,
@@ -43,3 +43,7 @@ def generate_random_string(string_len: int):
43
43
  # letters, digits, and symbols
44
44
  characters = string.ascii_letters + string.digits + string.punctuation
45
45
  return ''.join(random.choice(characters) for _ in range(string_len))
46
+
47
+
48
+ def get_position_in_line(text: str, position: int) -> int:
49
+ return position - text.rfind('\n', 0, position) - 1
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "cycode"
3
- version = "0.2.5.dev6" # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
3
+ version = "0.2.5.dev7" # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
4
4
  description = "Perform secrets/iac scans for your sources using Cycode's engine"
5
5
  keywords=["secret-scan", "cycode", "devops", "token", "secret", "security", "cycode", "code"]
6
6
  authors = ["Cycode <support@cycode.com>"]
@@ -1 +0,0 @@
1
- __version__ = '0.2.5.dev6' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag