Skip to content

Commit 6029de6

Browse files
committed
Merge branch 'main' into CM-46734-improve-help
# Conflicts: # cycode/cli/apps/scan/code_scanner.py # cycode/cli/apps/scan/pre_commit/pre_commit_command.py # cycode/cli/apps/scan/repository/repository_command.py # cycode/cli/consts.py # cycode/cli/printers/tables/sca_table_printer.py # cycode/cli/utils/scan_batch.py # tests/test_code_scanner.py
2 parents 0405c6b + 4681d32 commit 6029de6

File tree

4 files changed

+104
-12
lines changed

4 files changed

+104
-12
lines changed

.github/workflows/build_executable.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ jobs:
166166
shell: cmd
167167
env:
168168
SM_HOST: ${{ secrets.SM_HOST }}
169+
SM_KEYPAIR_ALIAS: ${{ secrets.SM_KEYPAIR_ALIAS }}
169170
SM_API_KEY: ${{ secrets.SM_API_KEY }}
170171
SM_CLIENT_CERT_PASSWORD: ${{ secrets.SM_CLIENT_CERT_PASSWORD }}
171172
SM_CODE_SIGNING_CERT_SHA1_HASH: ${{ secrets.SM_CODE_SIGNING_CERT_SHA1_HASH }}
@@ -174,7 +175,7 @@ jobs:
174175
curl -X GET https://one.digicert.com/signingmanager/api-ui/v1/releases/smtools-windows-x64.msi/download -H "x-api-key:%SM_API_KEY%" -o smtools-windows-x64.msi
175176
msiexec /i smtools-windows-x64.msi /quiet /qn
176177
C:\Windows\System32\certutil.exe -csp "DigiCert Signing Manager KSP" -key -user
177-
smksp_cert_sync.exe
178+
smctl windows certsync --keypair-alias=%SM_KEYPAIR_ALIAS%
178179
179180
:: sign executable
180181
signtool.exe sign /sha1 %SM_CODE_SIGNING_CERT_SHA1_HASH% /tr http://timestamp.digicert.com /td SHA256 /fd SHA256 ".\dist\cycode-cli.exe"

cycode/cli/apps/scan/code_scanner.py

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from cycode.cli.utils.progress_bar import ScanProgressBarSection
3535
from cycode.cli.utils.scan_batch import run_parallel_batched_scan
3636
from cycode.cli.utils.scan_utils import set_issue_detected
37+
from cycode.cli.utils.shell_executor import shell
3738
from cycode.cyclient.models import Detection, DetectionSchema, DetectionsPerFile, ZippedFileScanResult
3839
from cycode.logger import get_logger, set_logging_level
3940

@@ -661,6 +662,9 @@ def get_scan_parameters(ctx: typer.Context, paths: Optional[Tuple[str]] = None)
661662
return scan_parameters
662663

663664
remote_url = try_get_git_remote_url(paths[0])
665+
if not remote_url:
666+
remote_url = try_to_get_plastic_remote_url(paths[0])
667+
664668
if remote_url:
665669
# TODO(MarshalX): remove hardcode in context
666670
ctx.obj['remote_url'] = remote_url
@@ -679,6 +683,93 @@ def try_get_git_remote_url(path: str) -> Optional[str]:
679683
return None
680684

681685

686+
def _get_plastic_repository_name(path: str) -> Optional[str]:
687+
"""Gets the name of the Plastic repository from the current working directory.
688+
689+
The command to execute is:
690+
cm status --header --machinereadable --fieldseparator=":::"
691+
692+
Example of status header in machine-readable format:
693+
STATUS:::0:::Project/RepoName:::OrgName@ServerInfo
694+
"""
695+
696+
try:
697+
command = [
698+
'cm',
699+
'status',
700+
'--header',
701+
'--machinereadable',
702+
f'--fieldseparator={consts.PLASTIC_VCS_DATA_SEPARATOR}',
703+
]
704+
705+
status = shell(command=command, timeout=consts.PLASTIC_VSC_CLI_TIMEOUT, working_directory=path)
706+
if not status:
707+
logger.debug('Failed to get Plastic repository name (command failed)')
708+
return None
709+
710+
status_parts = status.split(consts.PLASTIC_VCS_DATA_SEPARATOR)
711+
if len(status_parts) < 2:
712+
logger.debug('Failed to parse Plastic repository name (command returned unexpected format)')
713+
return None
714+
715+
return status_parts[2].strip()
716+
except Exception as e:
717+
logger.debug('Failed to get Plastic repository name', exc_info=e)
718+
return None
719+
720+
721+
def _get_plastic_repository_list(working_dir: Optional[str] = None) -> Dict[str, str]:
722+
"""Gets the list of Plastic repositories and their GUIDs.
723+
724+
The command to execute is:
725+
cm repo list --format="{repname}:::{repguid}"
726+
727+
Example line with data:
728+
Project/RepoName:::tapo1zqt-wn99-4752-h61m-7d9k79d40r4v
729+
730+
Each line represents an individual repository.
731+
"""
732+
733+
repo_name_to_guid = {}
734+
735+
try:
736+
command = ['cm', 'repo', 'ls', f'--format={{repname}}{consts.PLASTIC_VCS_DATA_SEPARATOR}{{repguid}}']
737+
738+
status = shell(command=command, timeout=consts.PLASTIC_VSC_CLI_TIMEOUT, working_directory=working_dir)
739+
if not status:
740+
logger.debug('Failed to get Plastic repository list (command failed)')
741+
return repo_name_to_guid
742+
743+
status_lines = status.splitlines()
744+
for line in status_lines:
745+
data_parts = line.split(consts.PLASTIC_VCS_DATA_SEPARATOR)
746+
if len(data_parts) < 2:
747+
logger.debug('Failed to parse Plastic repository list line (unexpected format), %s', {'line': line})
748+
continue
749+
750+
repo_name, repo_guid = data_parts
751+
repo_name_to_guid[repo_name.strip()] = repo_guid.strip()
752+
753+
return repo_name_to_guid
754+
except Exception as e:
755+
logger.debug('Failed to get Plastic repository list', exc_info=e)
756+
return repo_name_to_guid
757+
758+
759+
def try_to_get_plastic_remote_url(path: str) -> Optional[str]:
760+
repository_name = _get_plastic_repository_name(path)
761+
if not repository_name:
762+
return None
763+
764+
repository_map = _get_plastic_repository_list(path)
765+
if repository_name not in repository_map:
766+
logger.debug('Failed to get Plastic repository GUID (repository not found in the list)')
767+
return None
768+
769+
repository_guid = repository_map[repository_name]
770+
return f'{consts.PLASTIC_VCS_REMOTE_URI_PREFIX}{repository_guid}'
771+
772+
682773
def exclude_irrelevant_detections(
683774
detections: List[Detection], scan_type: str, command_scan_type: str, severity_threshold: str
684775
) -> List[Detection]:
@@ -690,9 +781,7 @@ def exclude_irrelevant_detections(
690781
def _exclude_detections_by_severity(detections: List[Detection], severity_threshold: str) -> List[Detection]:
691782
relevant_detections = []
692783
for detection in detections:
693-
severity = detection.detection_details.get('advisory_severity')
694-
if not severity:
695-
severity = detection.severity
784+
severity = detection.severity
696785

697786
if _does_severity_match_severity_threshold(severity, severity_threshold):
698787
relevant_detections.append(detection)

cycode/cli/consts.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,11 @@
231231
# Example: A -> B -> C
232232
# Result: A -> ... -> C
233233
SCA_SHORTCUT_DEPENDENCY_PATHS = 2
234+
235+
SCA_SKIP_RESTORE_DEPENDENCIES_FLAG = 'no-restore'
236+
237+
SCA_GRADLE_ALL_SUB_PROJECTS_FLAG = 'gradle-all-sub-projects'
238+
239+
PLASTIC_VCS_DATA_SEPARATOR = ':::'
240+
PLASTIC_VSC_CLI_TIMEOUT = 10
241+
PLASTIC_VCS_REMOTE_URI_PREFIX = 'plastic::'

cycode/cli/printers/tables/sca_table_printer.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,8 @@ def _get_table(self, policy_id: str) -> Table:
8383
def _enrich_table_with_values(policy_id: str, table: Table, detection: Detection) -> None:
8484
detection_details = detection.detection_details
8585

86-
severity = None
87-
if policy_id == PACKAGE_VULNERABILITY_POLICY_ID:
88-
severity = detection_details.get('advisory_severity')
89-
elif policy_id == LICENSE_COMPLIANCE_POLICY_ID:
90-
severity = detection.severity
91-
92-
if severity:
93-
table.add_cell(SEVERITY_COLUMN, SeverityOption(severity))
86+
if detection.severity:
87+
table.add_cell(SEVERITY_COLUMN, SeverityOption(detection.severity))
9488
else:
9589
table.add_cell(SEVERITY_COLUMN, 'N/A')
9690

0 commit comments

Comments
 (0)