scanoss 1.30.0__py3-none-any.whl → 1.31.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scanoss/__init__.py +1 -1
- scanoss/cli.py +572 -188
- scanoss/data/build_date.txt +1 -1
- scanoss/export/dependency_track.py +101 -100
- scanoss/file_filters.py +1 -5
- scanoss/inspection/dependency_track/project_violation.py +449 -0
- scanoss/inspection/policy_check.py +54 -23
- scanoss/inspection/{component_summary.py → raw/component_summary.py} +3 -3
- scanoss/inspection/{copyleft.py → raw/copyleft.py} +63 -54
- scanoss/inspection/{license_summary.py → raw/license_summary.py} +5 -4
- scanoss/inspection/{inspect_base.py → raw/raw_base.py} +9 -6
- scanoss/inspection/{undeclared_component.py → raw/undeclared_component.py} +29 -25
- scanoss/services/dependency_track_service.py +131 -0
- {scanoss-1.30.0.dist-info → scanoss-1.31.1.dist-info}/METADATA +1 -1
- {scanoss-1.30.0.dist-info → scanoss-1.31.1.dist-info}/RECORD +19 -17
- {scanoss-1.30.0.dist-info → scanoss-1.31.1.dist-info}/WHEEL +0 -0
- {scanoss-1.30.0.dist-info → scanoss-1.31.1.dist-info}/entry_points.txt +0 -0
- {scanoss-1.30.0.dist-info → scanoss-1.31.1.dist-info}/licenses/LICENSE +0 -0
- {scanoss-1.30.0.dist-info → scanoss-1.31.1.dist-info}/top_level.txt +0 -0
scanoss/cli.py
CHANGED
|
@@ -33,12 +33,10 @@ from typing import List
|
|
|
33
33
|
import pypac
|
|
34
34
|
|
|
35
35
|
from scanoss.cryptography import Cryptography, create_cryptography_config_from_args
|
|
36
|
-
from scanoss.export.dependency_track import
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
from scanoss.inspection.component_summary import ComponentSummary
|
|
41
|
-
from scanoss.inspection.license_summary import LicenseSummary
|
|
36
|
+
from scanoss.export.dependency_track import DependencyTrackExporter
|
|
37
|
+
from scanoss.inspection.dependency_track.project_violation import DependencyTrackProjectViolationPolicyCheck
|
|
38
|
+
from scanoss.inspection.raw.component_summary import ComponentSummary
|
|
39
|
+
from scanoss.inspection.raw.license_summary import LicenseSummary
|
|
42
40
|
from scanoss.scanners.container_scanner import (
|
|
43
41
|
DEFAULT_SYFT_COMMAND,
|
|
44
42
|
DEFAULT_SYFT_TIMEOUT,
|
|
@@ -69,8 +67,8 @@ from .constants import (
|
|
|
69
67
|
from .csvoutput import CsvOutput
|
|
70
68
|
from .cyclonedx import CycloneDx
|
|
71
69
|
from .filecount import FileCount
|
|
72
|
-
from .inspection.copyleft import Copyleft
|
|
73
|
-
from .inspection.undeclared_component import UndeclaredComponent
|
|
70
|
+
from .inspection.raw.copyleft import Copyleft
|
|
71
|
+
from .inspection.raw.undeclared_component import UndeclaredComponent
|
|
74
72
|
from .results import Results
|
|
75
73
|
from .scancodedeps import ScancodeDeps
|
|
76
74
|
from .scanner import FAST_WINNOWING, Scanner
|
|
@@ -539,80 +537,293 @@ def setup_args() -> None: # noqa: PLR0912, PLR0915
|
|
|
539
537
|
)
|
|
540
538
|
p_results.set_defaults(func=results)
|
|
541
539
|
|
|
542
|
-
|
|
543
|
-
#
|
|
540
|
+
# =========================================================================
|
|
541
|
+
# INSPECT SUBCOMMAND - Analysis and validation of scan results
|
|
542
|
+
# =========================================================================
|
|
543
|
+
|
|
544
|
+
# Main inspect parser - provides tools for analyzing scan results
|
|
544
545
|
p_inspect = subparsers.add_parser(
|
|
545
|
-
'inspect',
|
|
546
|
+
'inspect',
|
|
547
|
+
aliases=['insp', 'ins'],
|
|
548
|
+
description=f'Inspect and analyse scan results: {__version__}',
|
|
549
|
+
help='Inspect and analyse scan results'
|
|
546
550
|
)
|
|
547
|
-
|
|
551
|
+
|
|
552
|
+
# Inspect sub-commands parser
|
|
548
553
|
p_inspect_sub = p_inspect.add_subparsers(
|
|
549
|
-
title='Inspect Commands',
|
|
554
|
+
title='Inspect Commands',
|
|
555
|
+
dest='subparsercmd',
|
|
556
|
+
description='Available inspection sub-commands',
|
|
557
|
+
help='Choose an inspection type'
|
|
558
|
+
)
|
|
559
|
+
|
|
560
|
+
# -------------------------------------------------------------------------
|
|
561
|
+
# RAW RESULTS INSPECTION - Analyse raw scan output
|
|
562
|
+
# -------------------------------------------------------------------------
|
|
563
|
+
|
|
564
|
+
# Raw results parser - handles inspection of unprocessed scan results
|
|
565
|
+
p_inspect_raw = p_inspect_sub.add_parser(
|
|
566
|
+
'raw',
|
|
567
|
+
description='Inspect and analyse SCANOSS raw scan results',
|
|
568
|
+
help='Analyse raw scan results for various compliance issues'
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
# Raw results sub-commands parser
|
|
572
|
+
p_inspect_raw_sub = p_inspect_raw.add_subparsers(
|
|
573
|
+
title='Raw Results Inspection Commands',
|
|
574
|
+
dest='subparser_subcmd',
|
|
575
|
+
description='Tools for analyzing raw scan results',
|
|
576
|
+
help='Choose a raw results analysis type'
|
|
550
577
|
)
|
|
551
578
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
579
|
+
# Copyleft license inspection - identifies copyleft license violations
|
|
580
|
+
p_inspect_raw_copyleft = p_inspect_raw_sub.add_parser(
|
|
581
|
+
'copyleft',
|
|
582
|
+
aliases=['cp'],
|
|
583
|
+
description='Identify components with copyleft licenses that may require compliance action',
|
|
584
|
+
help='Find copyleft license violations'
|
|
556
585
|
)
|
|
557
586
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
p_license_summary = p_inspect_sub.add_parser(
|
|
587
|
+
# License summary inspection - provides overview of all detected licenses
|
|
588
|
+
p_inspect_raw_license_summary = p_inspect_raw_sub.add_parser(
|
|
561
589
|
'license-summary',
|
|
562
590
|
aliases=['lic-summary', 'licsum'],
|
|
563
|
-
description='
|
|
564
|
-
help='
|
|
591
|
+
description='Generate comprehensive summary of all licenses found in scan results',
|
|
592
|
+
help='Generate license summary report'
|
|
565
593
|
)
|
|
566
594
|
|
|
567
|
-
|
|
595
|
+
# Component summary inspection - provides overview of all detected components
|
|
596
|
+
p_inspect_raw_component_summary = p_inspect_raw_sub.add_parser(
|
|
568
597
|
'component-summary',
|
|
569
598
|
aliases=['comp-summary', 'compsum'],
|
|
570
|
-
description='
|
|
571
|
-
help='
|
|
599
|
+
description='Generate comprehensive summary of all components found in scan results',
|
|
600
|
+
help='Generate component summary report'
|
|
601
|
+
)
|
|
602
|
+
|
|
603
|
+
# Undeclared components inspection - finds components not declared in SBOM
|
|
604
|
+
p_inspect_raw_undeclared = p_inspect_raw_sub.add_parser(
|
|
605
|
+
'undeclared',
|
|
606
|
+
aliases=['un'],
|
|
607
|
+
description='Identify components present in code but not declared in SBOM files',
|
|
608
|
+
help='Find undeclared components'
|
|
609
|
+
)
|
|
610
|
+
# SBOM format option for undeclared components inspection
|
|
611
|
+
p_inspect_raw_undeclared.add_argument(
|
|
612
|
+
'--sbom-format',
|
|
613
|
+
required=False,
|
|
614
|
+
choices=['legacy', 'settings'],
|
|
615
|
+
default='settings',
|
|
616
|
+
help='SBOM format type for comparison: legacy or settings (default)'
|
|
572
617
|
)
|
|
573
618
|
|
|
574
|
-
|
|
575
|
-
#
|
|
576
|
-
|
|
619
|
+
# -------------------------------------------------------------------------
|
|
620
|
+
# BACKWARD COMPATIBILITY - Support old inspect command format
|
|
621
|
+
# -------------------------------------------------------------------------
|
|
622
|
+
|
|
623
|
+
# Legacy copyleft inspection - backward compatibility for 'scanoss-py inspect copyleft'
|
|
624
|
+
p_inspect_legacy_copyleft = p_inspect_sub.add_parser(
|
|
625
|
+
'copyleft',
|
|
626
|
+
aliases=['cp'],
|
|
627
|
+
description='Identify components with copyleft licenses that may require compliance action',
|
|
628
|
+
help='Find copyleft license violations (legacy format)'
|
|
629
|
+
)
|
|
630
|
+
|
|
631
|
+
# Legacy undeclared components inspection - backward compatibility for 'scanoss-py inspect undeclared'
|
|
632
|
+
p_inspect_legacy_undeclared = p_inspect_sub.add_parser(
|
|
577
633
|
'undeclared',
|
|
578
634
|
aliases=['un'],
|
|
579
|
-
description='
|
|
580
|
-
help='
|
|
635
|
+
description='Identify components present in code but not declared in SBOM files',
|
|
636
|
+
help='Find undeclared components (legacy format)'
|
|
581
637
|
)
|
|
582
|
-
|
|
638
|
+
|
|
639
|
+
# SBOM format option for legacy undeclared components inspection
|
|
640
|
+
p_inspect_legacy_undeclared.add_argument(
|
|
583
641
|
'--sbom-format',
|
|
584
642
|
required=False,
|
|
585
643
|
choices=['legacy', 'settings'],
|
|
586
644
|
default='settings',
|
|
587
|
-
help='
|
|
645
|
+
help='SBOM format type for comparison: legacy or settings (default)'
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
# Legacy license summary inspection - backward compatibility for 'scanoss-py inspect license-summary'
|
|
649
|
+
p_inspect_legacy_license_summary = p_inspect_sub.add_parser(
|
|
650
|
+
'license-summary',
|
|
651
|
+
aliases=['lic-summary', 'licsum'],
|
|
652
|
+
description='Generate comprehensive summary of all licenses found in scan results',
|
|
653
|
+
help='Generate license summary report (legacy format)'
|
|
588
654
|
)
|
|
589
655
|
|
|
590
|
-
#
|
|
591
|
-
|
|
656
|
+
# Legacy component summary inspection - backward compatibility for 'scanoss-py inspect component-summary'
|
|
657
|
+
p_inspect_legacy_component_summary = p_inspect_sub.add_parser(
|
|
658
|
+
'component-summary',
|
|
659
|
+
aliases=['comp-summary', 'compsum'],
|
|
660
|
+
description='Generate comprehensive summary of all components found in scan results',
|
|
661
|
+
help='Generate component summary report (legacy format)'
|
|
662
|
+
)
|
|
663
|
+
|
|
664
|
+
# Applies the same configuration to both legacy and raw versions
|
|
665
|
+
# License filtering options - common to (legacy) copyleft and license summary commands
|
|
666
|
+
for p in [p_inspect_raw_copyleft, p_inspect_raw_license_summary,
|
|
667
|
+
p_inspect_legacy_copyleft, p_inspect_legacy_license_summary]:
|
|
592
668
|
p.add_argument(
|
|
593
669
|
'--include',
|
|
594
|
-
help='
|
|
670
|
+
help='Additional licenses to include in analysis (comma-separated list)'
|
|
595
671
|
)
|
|
596
672
|
p.add_argument(
|
|
597
673
|
'--exclude',
|
|
598
|
-
help='
|
|
674
|
+
help='Licenses to exclude from analysis (comma-separated list)'
|
|
599
675
|
)
|
|
600
676
|
p.add_argument(
|
|
601
677
|
'--explicit',
|
|
602
|
-
help='
|
|
678
|
+
help='Use only these specific licenses for analysis (comma-separated list)'
|
|
603
679
|
)
|
|
604
680
|
|
|
605
|
-
|
|
606
|
-
for p in [
|
|
607
|
-
p.add_argument(
|
|
608
|
-
|
|
681
|
+
# Common options for (legacy) copyleft and undeclared component inspection
|
|
682
|
+
for p in [p_inspect_raw_copyleft, p_inspect_raw_undeclared, p_inspect_legacy_copyleft, p_inspect_legacy_undeclared]:
|
|
683
|
+
p.add_argument(
|
|
684
|
+
'-i', '--input',
|
|
685
|
+
nargs='?',
|
|
686
|
+
help='Path to scan results file to analyse'
|
|
687
|
+
)
|
|
688
|
+
p.add_argument(
|
|
689
|
+
'-f', '--format',
|
|
690
|
+
required=False,
|
|
691
|
+
choices=['json', 'md', 'jira_md'],
|
|
692
|
+
default='json',
|
|
693
|
+
help='Output format: json (default), md (Markdown), or jira_md (JIRA Markdown)'
|
|
694
|
+
)
|
|
695
|
+
p.add_argument(
|
|
696
|
+
'-o', '--output',
|
|
697
|
+
type=str,
|
|
698
|
+
help='Save detailed results to specified file'
|
|
699
|
+
)
|
|
700
|
+
p.add_argument(
|
|
701
|
+
'-s', '--status',
|
|
702
|
+
type=str,
|
|
703
|
+
help='Save summary status report to Markdown file'
|
|
704
|
+
)
|
|
609
705
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
706
|
+
# Common options for (legacy) license and component summary commands
|
|
707
|
+
for p in [p_inspect_raw_license_summary, p_inspect_raw_component_summary,
|
|
708
|
+
p_inspect_legacy_license_summary, p_inspect_legacy_component_summary]:
|
|
709
|
+
p.add_argument(
|
|
710
|
+
'-i', '--input',
|
|
711
|
+
nargs='?',
|
|
712
|
+
help='Path to scan results file to analyse'
|
|
713
|
+
)
|
|
714
|
+
p.add_argument(
|
|
715
|
+
'-o', '--output',
|
|
716
|
+
type=str,
|
|
717
|
+
help='Save summary report to specified file'
|
|
718
|
+
)
|
|
614
719
|
|
|
615
|
-
|
|
720
|
+
# -------------------------------------------------------------------------
|
|
721
|
+
# DEPENDENCY TRACK INSPECTION - Analyse Dependency Track project data
|
|
722
|
+
# -------------------------------------------------------------------------
|
|
723
|
+
|
|
724
|
+
# Dependency Track parser - handles inspection of DT project status and violations
|
|
725
|
+
p_dep_track_sub = p_inspect_sub.add_parser(
|
|
726
|
+
'dependency-track',
|
|
727
|
+
aliases=['dt'],
|
|
728
|
+
description='Inspect and analyse Dependency Track project status and policy violations',
|
|
729
|
+
help='Analyse Dependency Track projects'
|
|
730
|
+
)
|
|
731
|
+
|
|
732
|
+
# Dependency Track sub-commands parser
|
|
733
|
+
p_inspect_dep_track_sub = p_dep_track_sub.add_subparsers(
|
|
734
|
+
title='Dependency Track Inspection Commands',
|
|
735
|
+
dest='subparser_subcmd',
|
|
736
|
+
description='Tools for analysing Dependency Track project data',
|
|
737
|
+
help='Choose a Dependency Track analysis type'
|
|
738
|
+
)
|
|
739
|
+
|
|
740
|
+
# Project violations inspection - analyses policy violations in DT projects
|
|
741
|
+
p_inspect_dt_project_violation = p_inspect_dep_track_sub.add_parser(
|
|
742
|
+
'project-violations',
|
|
743
|
+
aliases=['pv'],
|
|
744
|
+
description='Analyse policy violations and compliance issues in Dependency Track projects',
|
|
745
|
+
help='Inspect project policy violations'
|
|
746
|
+
)
|
|
747
|
+
# Dependency Track connection and authentication options
|
|
748
|
+
p_inspect_dt_project_violation.add_argument(
|
|
749
|
+
'--url',
|
|
750
|
+
required=True,
|
|
751
|
+
type=str,
|
|
752
|
+
help='Dependency Track server base URL (e.g., https://dtrack.example.com)'
|
|
753
|
+
)
|
|
754
|
+
p_inspect_dt_project_violation.add_argument(
|
|
755
|
+
'--upload-token', '-ut',
|
|
756
|
+
required=False,
|
|
757
|
+
type=str,
|
|
758
|
+
help='Project-specific upload token for accessing DT project data'
|
|
759
|
+
)
|
|
760
|
+
p_inspect_dt_project_violation.add_argument(
|
|
761
|
+
'--project-id', '-pid',
|
|
762
|
+
required=False,
|
|
763
|
+
type=str,
|
|
764
|
+
help='Dependency Track project UUID to inspect'
|
|
765
|
+
)
|
|
766
|
+
p_inspect_dt_project_violation.add_argument(
|
|
767
|
+
'--apikey', '-k',
|
|
768
|
+
required=True,
|
|
769
|
+
type=str,
|
|
770
|
+
help='Dependency Track API key for authentication'
|
|
771
|
+
)
|
|
772
|
+
p_inspect_dt_project_violation.add_argument(
|
|
773
|
+
'--project-name', '-pn',
|
|
774
|
+
required=False,
|
|
775
|
+
type=str,
|
|
776
|
+
help='Dependency Track project name'
|
|
777
|
+
)
|
|
778
|
+
p_inspect_dt_project_violation.add_argument(
|
|
779
|
+
'--project-version', '-pv',
|
|
780
|
+
required=False,
|
|
781
|
+
type=str,
|
|
782
|
+
help='Dependency Track project version'
|
|
783
|
+
)
|
|
784
|
+
p_inspect_dt_project_violation.add_argument(
|
|
785
|
+
'--output', '-o',
|
|
786
|
+
required=False,
|
|
787
|
+
type=str,
|
|
788
|
+
help='Save inspection results to specified file'
|
|
789
|
+
)
|
|
790
|
+
p_inspect_dt_project_violation.add_argument(
|
|
791
|
+
'--status',
|
|
792
|
+
required=False,
|
|
793
|
+
type=str,
|
|
794
|
+
help='Save summary status report to specified file'
|
|
795
|
+
)
|
|
796
|
+
p_inspect_dt_project_violation.add_argument(
|
|
797
|
+
'--format', '-f',
|
|
798
|
+
required=False,
|
|
799
|
+
choices=['json', 'md'],
|
|
800
|
+
default='json',
|
|
801
|
+
help='Output format: json (default) or md (Markdown)'
|
|
802
|
+
)
|
|
803
|
+
p_inspect_dt_project_violation.add_argument(
|
|
804
|
+
'--timeout', '-M',
|
|
805
|
+
required=False,
|
|
806
|
+
default='300',
|
|
807
|
+
help='Timeout (in seconds) for API communication (optional - default 300 sec)'
|
|
808
|
+
)
|
|
809
|
+
|
|
810
|
+
# TODO Move to the command call def location
|
|
811
|
+
# RAW results
|
|
812
|
+
p_inspect_raw_undeclared.set_defaults(func=inspect_undeclared)
|
|
813
|
+
p_inspect_raw_copyleft.set_defaults(func=inspect_copyleft)
|
|
814
|
+
p_inspect_raw_license_summary.set_defaults(func=inspect_license_summary)
|
|
815
|
+
p_inspect_raw_component_summary.set_defaults(func=inspect_component_summary)
|
|
816
|
+
# Legacy backward compatibility commands
|
|
817
|
+
p_inspect_legacy_copyleft.set_defaults(func=inspect_copyleft)
|
|
818
|
+
p_inspect_legacy_undeclared.set_defaults(func=inspect_undeclared)
|
|
819
|
+
p_inspect_legacy_license_summary.set_defaults(func=inspect_license_summary)
|
|
820
|
+
p_inspect_legacy_component_summary.set_defaults(func=inspect_component_summary)
|
|
821
|
+
# Dependency Track
|
|
822
|
+
p_inspect_dt_project_violation.set_defaults(func=inspect_dep_track_project_violations)
|
|
823
|
+
|
|
824
|
+
# =========================================================================
|
|
825
|
+
# END INSPECT SUBCOMMAND CONFIGURATION
|
|
826
|
+
# =========================================================================
|
|
616
827
|
|
|
617
828
|
# Sub-command: export
|
|
618
829
|
p_export = subparsers.add_parser(
|
|
@@ -637,11 +848,12 @@ def setup_args() -> None: # noqa: PLR0912, PLR0915
|
|
|
637
848
|
help='Upload SBOM files to Dependency Track',
|
|
638
849
|
)
|
|
639
850
|
e_dt.add_argument('-i', '--input', type=str, required=True, help='Input SBOM file (CycloneDX JSON format)')
|
|
640
|
-
e_dt.add_argument('--
|
|
641
|
-
e_dt.add_argument('--
|
|
642
|
-
e_dt.add_argument('--
|
|
643
|
-
e_dt.add_argument('--
|
|
644
|
-
e_dt.add_argument('--
|
|
851
|
+
e_dt.add_argument('--url', type=str, required=True, help='Dependency Track base URL')
|
|
852
|
+
e_dt.add_argument('--apikey', '-k', type=str, required=True, help='Dependency Track API key')
|
|
853
|
+
e_dt.add_argument('--output', '-o', type=str, help='File to save export token and uuid into')
|
|
854
|
+
e_dt.add_argument('--project-id', '-pid', type=str, help='Dependency Track project UUID')
|
|
855
|
+
e_dt.add_argument('--project-name', '-pn', type=str, help='Dependency Track project name')
|
|
856
|
+
e_dt.add_argument('--project-version', '-pv', type=str, help='Dependency Track project version')
|
|
645
857
|
e_dt.set_defaults(func=export_dt)
|
|
646
858
|
|
|
647
859
|
# Sub-command: folder-scan
|
|
@@ -746,19 +958,6 @@ def setup_args() -> None: # noqa: PLR0912, PLR0915
|
|
|
746
958
|
help='Skip default settings file (scanoss.json) if it exists',
|
|
747
959
|
)
|
|
748
960
|
|
|
749
|
-
for p in [p_copyleft, p_undeclared]:
|
|
750
|
-
p.add_argument('-i', '--input', nargs='?', help='Path to results file')
|
|
751
|
-
p.add_argument(
|
|
752
|
-
'-f',
|
|
753
|
-
'--format',
|
|
754
|
-
required=False,
|
|
755
|
-
choices=['json', 'md', 'jira_md'],
|
|
756
|
-
default='json',
|
|
757
|
-
help='Output format (default: json)',
|
|
758
|
-
)
|
|
759
|
-
p.add_argument('-o', '--output', type=str, help='Save details into a file')
|
|
760
|
-
p.add_argument('-s', '--status', type=str, help='Save summary data into Markdown file')
|
|
761
|
-
|
|
762
961
|
# Global Scan command options
|
|
763
962
|
for p in [p_scan, p_cs]:
|
|
764
963
|
p.add_argument(
|
|
@@ -886,10 +1085,15 @@ def setup_args() -> None: # noqa: PLR0912, PLR0915
|
|
|
886
1085
|
c_versions,
|
|
887
1086
|
c_semgrep,
|
|
888
1087
|
p_results,
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
1088
|
+
p_inspect_raw_undeclared,
|
|
1089
|
+
p_inspect_raw_copyleft,
|
|
1090
|
+
p_inspect_raw_license_summary,
|
|
1091
|
+
p_inspect_raw_component_summary,
|
|
1092
|
+
p_inspect_legacy_copyleft,
|
|
1093
|
+
p_inspect_legacy_undeclared,
|
|
1094
|
+
p_inspect_legacy_license_summary,
|
|
1095
|
+
p_inspect_legacy_component_summary,
|
|
1096
|
+
p_inspect_dt_project_violation,
|
|
893
1097
|
c_provenance,
|
|
894
1098
|
p_folder_scan,
|
|
895
1099
|
p_folder_hash,
|
|
@@ -916,6 +1120,9 @@ def setup_args() -> None: # noqa: PLR0912, PLR0915
|
|
|
916
1120
|
) and not args.subparsercmd:
|
|
917
1121
|
parser.parse_args([args.subparser, '--help']) # Force utils helps to be displayed
|
|
918
1122
|
sys.exit(1)
|
|
1123
|
+
elif (args.subparser in 'inspect') and (args.subparsercmd in ('raw', 'dt')) and (args.subparser_subcmd is None):
|
|
1124
|
+
parser.parse_args([args.subparser, args.subparsercmd, '--help']) # Force utils helps to be displayed
|
|
1125
|
+
sys.exit(1)
|
|
919
1126
|
args.func(parser, args) # Execute the function associated with the sub-command
|
|
920
1127
|
|
|
921
1128
|
|
|
@@ -949,16 +1156,14 @@ def file_count(parser, args):
|
|
|
949
1156
|
print_stderr('Please specify a folder')
|
|
950
1157
|
parser.parse_args([args.subparser, '-h'])
|
|
951
1158
|
sys.exit(1)
|
|
952
|
-
scan_output: str = None
|
|
953
1159
|
if args.output:
|
|
954
|
-
|
|
955
|
-
open(scan_output, 'w').close()
|
|
1160
|
+
initialise_empty_file(args.output)
|
|
956
1161
|
|
|
957
1162
|
counter = FileCount(
|
|
958
1163
|
debug=args.debug,
|
|
959
1164
|
quiet=args.quiet,
|
|
960
1165
|
trace=args.trace,
|
|
961
|
-
scan_output=
|
|
1166
|
+
scan_output=args.output,
|
|
962
1167
|
hidden_files_folders=args.all_hidden,
|
|
963
1168
|
)
|
|
964
1169
|
if not os.path.exists(args.scan_dir):
|
|
@@ -987,10 +1192,8 @@ def wfp(parser, args):
|
|
|
987
1192
|
sys.exit(1)
|
|
988
1193
|
if args.strip_hpsm and not args.hpsm and not args.quiet:
|
|
989
1194
|
print_stderr('Warning: --strip-hpsm option supplied without enabling HPSM (--hpsm). Ignoring.')
|
|
990
|
-
scan_output: str = None
|
|
991
1195
|
if args.output:
|
|
992
|
-
|
|
993
|
-
open(scan_output, 'w').close()
|
|
1196
|
+
initialise_empty_file(args.output)
|
|
994
1197
|
|
|
995
1198
|
# Load scan settings
|
|
996
1199
|
scan_settings = None
|
|
@@ -1023,15 +1226,15 @@ def wfp(parser, args):
|
|
|
1023
1226
|
)
|
|
1024
1227
|
if args.stdin:
|
|
1025
1228
|
contents = sys.stdin.buffer.read()
|
|
1026
|
-
scanner.wfp_contents(args.stdin, contents,
|
|
1229
|
+
scanner.wfp_contents(args.stdin, contents, args.output)
|
|
1027
1230
|
elif args.scan_dir:
|
|
1028
1231
|
if not os.path.exists(args.scan_dir):
|
|
1029
1232
|
print_stderr(f'Error: File or folder specified does not exist: {args.scan_dir}.')
|
|
1030
1233
|
sys.exit(1)
|
|
1031
1234
|
if os.path.isdir(args.scan_dir):
|
|
1032
|
-
scanner.wfp_folder(args.scan_dir,
|
|
1235
|
+
scanner.wfp_folder(args.scan_dir, args.output)
|
|
1033
1236
|
elif os.path.isfile(args.scan_dir):
|
|
1034
|
-
scanner.wfp_file(args.scan_dir,
|
|
1237
|
+
scanner.wfp_file(args.scan_dir, args.output)
|
|
1035
1238
|
else:
|
|
1036
1239
|
print_stderr(f'Error: Path specified is neither a file or a folder: {args.scan_dir}.')
|
|
1037
1240
|
sys.exit(1)
|
|
@@ -1128,10 +1331,8 @@ def scan(parser, args): # noqa: PLR0912, PLR0915
|
|
|
1128
1331
|
if args.strip_hpsm and not args.hpsm and not args.quiet:
|
|
1129
1332
|
print_stderr('Warning: --strip-hpsm option supplied without enabling HPSM (--hpsm). Ignoring.')
|
|
1130
1333
|
|
|
1131
|
-
scan_output: str = None
|
|
1132
1334
|
if args.output:
|
|
1133
|
-
|
|
1134
|
-
open(scan_output, 'w').close()
|
|
1335
|
+
initialise_empty_file(args.output)
|
|
1135
1336
|
output_format = args.format if args.format else 'plain'
|
|
1136
1337
|
flags = args.flags if args.flags else None
|
|
1137
1338
|
if args.debug and not args.quiet:
|
|
@@ -1186,7 +1387,7 @@ def scan(parser, args): # noqa: PLR0912, PLR0915
|
|
|
1186
1387
|
quiet=args.quiet,
|
|
1187
1388
|
api_key=args.key,
|
|
1188
1389
|
url=args.apiurl,
|
|
1189
|
-
scan_output=
|
|
1390
|
+
scan_output=args.output,
|
|
1190
1391
|
output_format=output_format,
|
|
1191
1392
|
flags=flags,
|
|
1192
1393
|
nb_threads=args.threads,
|
|
@@ -1298,16 +1499,15 @@ def dependency(parser, args):
|
|
|
1298
1499
|
if not os.path.exists(args.scan_loc):
|
|
1299
1500
|
print_stderr(f'Error: File or folder specified does not exist: {args.scan_loc}.')
|
|
1300
1501
|
sys.exit(1)
|
|
1301
|
-
scan_output: str = None
|
|
1302
1502
|
if args.output:
|
|
1303
|
-
|
|
1304
|
-
open(scan_output, 'w').close()
|
|
1503
|
+
initialise_empty_file(args.output)
|
|
1305
1504
|
|
|
1306
1505
|
sc_deps = ScancodeDeps(
|
|
1307
1506
|
debug=args.debug, quiet=args.quiet, trace=args.trace, sc_command=args.sc_command, timeout=args.sc_timeout
|
|
1308
1507
|
)
|
|
1309
|
-
if not sc_deps.get_dependencies(what_to_scan=args.scan_loc, result_output=
|
|
1508
|
+
if not sc_deps.get_dependencies(what_to_scan=args.scan_loc, result_output=args.output):
|
|
1310
1509
|
sys.exit(1)
|
|
1510
|
+
return None
|
|
1311
1511
|
|
|
1312
1512
|
|
|
1313
1513
|
def convert(parser, args):
|
|
@@ -1346,179 +1546,339 @@ def convert(parser, args):
|
|
|
1346
1546
|
sys.exit(1)
|
|
1347
1547
|
|
|
1348
1548
|
|
|
1349
|
-
|
|
1549
|
+
# =============================================================================
|
|
1550
|
+
# INSPECT COMMAND HANDLERS - Functions that execute inspection operations
|
|
1551
|
+
# =============================================================================
|
|
1552
|
+
|
|
1350
1553
|
def inspect_copyleft(parser, args):
|
|
1351
1554
|
"""
|
|
1352
|
-
|
|
1555
|
+
Handle copyleft license inspection command.
|
|
1556
|
+
|
|
1557
|
+
Analyses scan results to identify components using copyleft licenses
|
|
1558
|
+
that may require compliance actions such as source code disclosure.
|
|
1559
|
+
|
|
1353
1560
|
Parameters
|
|
1354
1561
|
----------
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1562
|
+
parser : ArgumentParser
|
|
1563
|
+
Command line parser object for help display
|
|
1564
|
+
args : Namespace
|
|
1565
|
+
Parsed command line arguments containing:
|
|
1566
|
+
- input: Path to scan results file
|
|
1567
|
+
- output: Optional output file path
|
|
1568
|
+
- status: Optional status summary file path
|
|
1569
|
+
- format: Output format (json, md, jira_md)
|
|
1570
|
+
- include/exclude/explicit: License filter options
|
|
1571
|
+
"""
|
|
1572
|
+
# Validate required input file parameter
|
|
1360
1573
|
if args.input is None:
|
|
1361
|
-
print_stderr('
|
|
1362
|
-
parser.parse_args([args.subparser, args.subparsercmd, '-h'])
|
|
1574
|
+
print_stderr('ERROR: Input file is required for copyleft inspection')
|
|
1575
|
+
parser.parse_args([args.subparser, args.subparsercmd, args.subparser_subcmd, '-h'])
|
|
1363
1576
|
sys.exit(1)
|
|
1364
|
-
output
|
|
1577
|
+
# Initialise output file if specified
|
|
1365
1578
|
if args.output:
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
status_output: str = None
|
|
1579
|
+
initialise_empty_file(args.output)
|
|
1580
|
+
# Initialise status summary file if specified
|
|
1370
1581
|
if args.status:
|
|
1371
|
-
|
|
1372
|
-
|
|
1582
|
+
initialise_empty_file(args.status)
|
|
1583
|
+
try:
|
|
1584
|
+
# Create and configure copyleft inspector
|
|
1585
|
+
i_copyleft = Copyleft(
|
|
1586
|
+
debug=args.debug,
|
|
1587
|
+
trace=args.trace,
|
|
1588
|
+
quiet=args.quiet,
|
|
1589
|
+
filepath=args.input,
|
|
1590
|
+
format_type=args.format,
|
|
1591
|
+
status=args.status,
|
|
1592
|
+
output=args.output,
|
|
1593
|
+
include=args.include, # Additional licenses to check
|
|
1594
|
+
exclude=args.exclude, # Licenses to ignore
|
|
1595
|
+
explicit=args.explicit, # Explicit license list
|
|
1596
|
+
)
|
|
1373
1597
|
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
include=args.include,
|
|
1383
|
-
exclude=args.exclude,
|
|
1384
|
-
explicit=args.explicit,
|
|
1385
|
-
)
|
|
1386
|
-
status, _ = i_copyleft.run()
|
|
1387
|
-
sys.exit(status)
|
|
1598
|
+
# Execute inspection and exit with appropriate status code
|
|
1599
|
+
status, _ = i_copyleft.run()
|
|
1600
|
+
sys.exit(status)
|
|
1601
|
+
except Exception as e:
|
|
1602
|
+
print_stderr(e)
|
|
1603
|
+
if args.debug:
|
|
1604
|
+
traceback.print_exc()
|
|
1605
|
+
sys.exit(1)
|
|
1388
1606
|
|
|
1389
1607
|
|
|
1390
1608
|
def inspect_undeclared(parser, args):
|
|
1391
1609
|
"""
|
|
1392
|
-
|
|
1610
|
+
Handle undeclared components inspection command.
|
|
1611
|
+
|
|
1612
|
+
Analyses scan results to identify components that are present in the
|
|
1613
|
+
codebase but not declared in SBOM or manifest files, which may indicate
|
|
1614
|
+
security or compliance risks.
|
|
1615
|
+
|
|
1393
1616
|
Parameters
|
|
1394
1617
|
----------
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1618
|
+
parser : ArgumentParser
|
|
1619
|
+
Command line parser object for help display
|
|
1620
|
+
args : Namespace
|
|
1621
|
+
Parsed command line arguments containing:
|
|
1622
|
+
- input: Path to scan results file
|
|
1623
|
+
- output: Optional output file path
|
|
1624
|
+
- status: Optional status summary file path
|
|
1625
|
+
- format: Output format (json, md, jira_md)
|
|
1626
|
+
- sbom_format: SBOM format type (legacy, settings)
|
|
1627
|
+
"""
|
|
1628
|
+
# Validate required input file parameter
|
|
1400
1629
|
if args.input is None:
|
|
1401
|
-
print_stderr('
|
|
1402
|
-
parser.parse_args([args.subparser, args.subparsercmd, '-h'])
|
|
1630
|
+
print_stderr('ERROR: Input file is required for undeclared component inspection')
|
|
1631
|
+
parser.parse_args([args.subparser, args.subparsercmd, args.subparser_subcmd, '-h'])
|
|
1403
1632
|
sys.exit(1)
|
|
1404
|
-
|
|
1633
|
+
|
|
1634
|
+
# Initialise output file if specified
|
|
1405
1635
|
if args.output:
|
|
1406
|
-
|
|
1407
|
-
open(output, 'w').close()
|
|
1636
|
+
initialise_empty_file(args.output)
|
|
1408
1637
|
|
|
1409
|
-
|
|
1638
|
+
# Initialise status summary file if specified
|
|
1410
1639
|
if args.status:
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1640
|
+
initialise_empty_file(args.status)
|
|
1641
|
+
|
|
1642
|
+
try:
|
|
1643
|
+
# Create and configure undeclared component inspector
|
|
1644
|
+
i_undeclared = UndeclaredComponent(
|
|
1645
|
+
debug=args.debug,
|
|
1646
|
+
trace=args.trace,
|
|
1647
|
+
quiet=args.quiet,
|
|
1648
|
+
filepath=args.input,
|
|
1649
|
+
format_type=args.format,
|
|
1650
|
+
status=args.status,
|
|
1651
|
+
output=args.output,
|
|
1652
|
+
sbom_format=args.sbom_format, # Format for SBOM comparison
|
|
1653
|
+
)
|
|
1654
|
+
|
|
1655
|
+
# Execute inspection and exit with appropriate status code
|
|
1656
|
+
status, _ = i_undeclared.run()
|
|
1657
|
+
sys.exit(status)
|
|
1658
|
+
except Exception as e:
|
|
1659
|
+
print_stderr(e)
|
|
1660
|
+
if args.debug:
|
|
1661
|
+
traceback.print_exc()
|
|
1662
|
+
sys.exit(1)
|
|
1425
1663
|
|
|
1426
1664
|
|
|
1427
1665
|
def inspect_license_summary(parser, args):
|
|
1428
1666
|
"""
|
|
1429
|
-
|
|
1667
|
+
Handle license summary inspection command.
|
|
1668
|
+
|
|
1669
|
+
Generates comprehensive summary of all licenses detected in scan results,
|
|
1670
|
+
including license counts, risk levels, and compliance recommendations.
|
|
1671
|
+
|
|
1430
1672
|
Parameters
|
|
1431
1673
|
----------
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1674
|
+
parser : ArgumentParser
|
|
1675
|
+
Command line parser object for help display
|
|
1676
|
+
args : Namespace
|
|
1677
|
+
Parsed command line arguments containing:
|
|
1678
|
+
- input: Path to scan results file
|
|
1679
|
+
- output: Optional output file path
|
|
1680
|
+
- include/exclude/explicit: License filter options
|
|
1681
|
+
"""
|
|
1682
|
+
# Validate required input file parameter
|
|
1437
1683
|
if args.input is None:
|
|
1438
|
-
print_stderr('
|
|
1439
|
-
parser.parse_args([args.subparser, args.subparsercmd, '-h'])
|
|
1684
|
+
print_stderr('ERROR: Input file is required for license summary')
|
|
1685
|
+
parser.parse_args([args.subparser, args.subparsercmd, args.subparser_subcmd, '-h'])
|
|
1440
1686
|
sys.exit(1)
|
|
1441
|
-
|
|
1687
|
+
|
|
1688
|
+
# Initialise output file if specified
|
|
1442
1689
|
if args.output:
|
|
1443
|
-
|
|
1444
|
-
open(output, 'w').close()
|
|
1690
|
+
initialise_empty_file(args.output)
|
|
1445
1691
|
|
|
1692
|
+
# Create and configure license summary generator
|
|
1446
1693
|
i_license_summary = LicenseSummary(
|
|
1447
1694
|
debug=args.debug,
|
|
1448
1695
|
trace=args.trace,
|
|
1449
1696
|
quiet=args.quiet,
|
|
1450
1697
|
filepath=args.input,
|
|
1451
|
-
output=output,
|
|
1452
|
-
include=args.include,
|
|
1453
|
-
exclude=args.exclude,
|
|
1454
|
-
explicit=args.explicit,
|
|
1698
|
+
output=args.output,
|
|
1699
|
+
include=args.include, # Additional licenses to include
|
|
1700
|
+
exclude=args.exclude, # Licenses to exclude from summary
|
|
1701
|
+
explicit=args.explicit, # Explicit license list to summarize
|
|
1455
1702
|
)
|
|
1456
|
-
|
|
1457
|
-
|
|
1703
|
+
try:
|
|
1704
|
+
# Execute summary generation
|
|
1705
|
+
i_license_summary.run()
|
|
1706
|
+
except Exception as e:
|
|
1707
|
+
print_stderr(e)
|
|
1708
|
+
if args.debug:
|
|
1709
|
+
traceback.print_exc()
|
|
1710
|
+
sys.exit(1)
|
|
1458
1711
|
|
|
1459
1712
|
def inspect_component_summary(parser, args):
|
|
1460
1713
|
"""
|
|
1461
|
-
|
|
1714
|
+
Handle component summary inspection command.
|
|
1715
|
+
|
|
1716
|
+
Generates a comprehensive summary of all components detected in scan results,
|
|
1717
|
+
including component counts, versions, match types, and security information.
|
|
1718
|
+
|
|
1462
1719
|
Parameters
|
|
1463
1720
|
----------
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1721
|
+
parser : ArgumentParser
|
|
1722
|
+
Command line parser object for help display
|
|
1723
|
+
args : Namespace
|
|
1724
|
+
Parsed command line arguments containing:
|
|
1725
|
+
- input: Path to scan results file
|
|
1726
|
+
- output: Optional output file path
|
|
1727
|
+
"""
|
|
1728
|
+
# Validate required input file parameter
|
|
1469
1729
|
if args.input is None:
|
|
1470
|
-
print_stderr('
|
|
1471
|
-
parser.parse_args([args.subparser, args.subparsercmd, '-h'])
|
|
1730
|
+
print_stderr('ERROR: Input file is required for component summary')
|
|
1731
|
+
parser.parse_args([args.subparser, args.subparsercmd, args.subparser_subcmd, '-h'])
|
|
1472
1732
|
sys.exit(1)
|
|
1473
|
-
|
|
1733
|
+
|
|
1734
|
+
# Initialise an output file if specified
|
|
1474
1735
|
if args.output:
|
|
1475
|
-
output
|
|
1476
|
-
open(output, 'w').close()
|
|
1736
|
+
initialise_empty_file(args.output) # Create/clear output file
|
|
1477
1737
|
|
|
1738
|
+
# Create and configure component summary generator
|
|
1478
1739
|
i_component_summary = ComponentSummary(
|
|
1479
1740
|
debug=args.debug,
|
|
1480
1741
|
trace=args.trace,
|
|
1481
1742
|
quiet=args.quiet,
|
|
1482
1743
|
filepath=args.input,
|
|
1483
|
-
output=output,
|
|
1744
|
+
output=args.output,
|
|
1484
1745
|
)
|
|
1485
|
-
i_component_summary.run()
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
################################ End inspect handlers ################################
|
|
1489
1746
|
|
|
1747
|
+
try:
|
|
1748
|
+
# Execute summary generation
|
|
1749
|
+
i_component_summary.run()
|
|
1750
|
+
except Exception as e:
|
|
1751
|
+
print_stderr(e)
|
|
1752
|
+
if args.debug:
|
|
1753
|
+
traceback.print_exc()
|
|
1754
|
+
sys.exit(1)
|
|
1490
1755
|
|
|
1491
|
-
def
|
|
1756
|
+
def inspect_dep_track_project_violations(parser, args):
|
|
1492
1757
|
"""
|
|
1493
|
-
|
|
1758
|
+
Handle Dependency Track project inspection command.
|
|
1759
|
+
|
|
1760
|
+
Analyses Dependency Track projects for policy violations, security issues,
|
|
1761
|
+
and compliance status. Connects to DT API to retrieve project data and
|
|
1762
|
+
generate detailed violation reports.
|
|
1763
|
+
|
|
1494
1764
|
Parameters
|
|
1495
1765
|
----------
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1766
|
+
parser : ArgumentParser
|
|
1767
|
+
Command line parser object for help display
|
|
1768
|
+
args : Namespace
|
|
1769
|
+
Parsed command line arguments containing:
|
|
1770
|
+
- url: Dependency Track base URL
|
|
1771
|
+
- apikey: API key for authentication
|
|
1772
|
+
- project_id: Project UUID to inspect
|
|
1773
|
+
- project_name: Project name to inspect
|
|
1774
|
+
- project_version: Project version to inspect
|
|
1775
|
+
- upload_token: Upload token for project access
|
|
1776
|
+
- output: Optional output file path
|
|
1777
|
+
- format: Output format (json, md)
|
|
1778
|
+
- timeout: Optional timeout for API requests
|
|
1779
|
+
|
|
1780
|
+
"""
|
|
1781
|
+
# Make sure we have project id/project name and version
|
|
1782
|
+
_dt_args_validator(parser, args)
|
|
1783
|
+
# Initialise the output file if specified
|
|
1784
|
+
if args.output:
|
|
1785
|
+
initialise_empty_file(args.output)
|
|
1786
|
+
# Create and configure Dependency Track inspector
|
|
1787
|
+
try:
|
|
1788
|
+
dt_proj_violations = DependencyTrackProjectViolationPolicyCheck(
|
|
1789
|
+
debug=args.debug,
|
|
1790
|
+
trace=args.trace,
|
|
1791
|
+
quiet=args.quiet,
|
|
1792
|
+
output=args.output,
|
|
1793
|
+
status= args.status,
|
|
1794
|
+
format_type=args.format,
|
|
1795
|
+
url=args.url, # DT server URL
|
|
1796
|
+
api_key=args.apikey, # Authentication key
|
|
1797
|
+
project_id=args.project_id, # Target project UUID
|
|
1798
|
+
upload_token=args.upload_token, # Upload access token
|
|
1799
|
+
project_name=args.project_name, # DT project name
|
|
1800
|
+
project_version=args.project_version, # DT project version
|
|
1801
|
+
timeout=args.timeout,
|
|
1802
|
+
)
|
|
1803
|
+
# Execute inspection and exit with appropriate status code
|
|
1804
|
+
status = dt_proj_violations.run()
|
|
1805
|
+
sys.exit(status)
|
|
1806
|
+
except Exception as e:
|
|
1807
|
+
print_stderr(e)
|
|
1808
|
+
if args.debug:
|
|
1809
|
+
traceback.print_exc()
|
|
1810
|
+
sys.exit(1)
|
|
1811
|
+
|
|
1812
|
+
|
|
1813
|
+
# =============================================================================
|
|
1814
|
+
# END INSPECT COMMAND HANDLERS
|
|
1815
|
+
# =============================================================================
|
|
1816
|
+
|
|
1817
|
+
def export_dt(parser, args):
|
|
1500
1818
|
"""
|
|
1819
|
+
Validates and exports a Software Bill of Materials (SBOM) to a Dependency-Track server.
|
|
1820
|
+
|
|
1821
|
+
Parameters:
|
|
1822
|
+
parser (argparse.ArgumentParser): The argument parser to validate input arguments.
|
|
1823
|
+
args (argparse.Namespace): Parsed arguments passed to the command.
|
|
1501
1824
|
|
|
1825
|
+
Raises:
|
|
1826
|
+
SystemExit: If argument validation fails or uploading the SBOM to the Dependency-Track server
|
|
1827
|
+
is unsuccessful.
|
|
1828
|
+
"""
|
|
1829
|
+
# Make sure we have project id/project name and version
|
|
1830
|
+
_dt_args_validator(parser, args)
|
|
1831
|
+
if args.output:
|
|
1832
|
+
initialise_empty_file(args.output)
|
|
1833
|
+
if not args.quiet:
|
|
1834
|
+
print_stderr(f'Outputting export data result to: {args.output}')
|
|
1502
1835
|
try:
|
|
1503
|
-
config = create_dependency_track_exporter_config_from_args(args)
|
|
1504
1836
|
dt_exporter = DependencyTrackExporter(
|
|
1505
|
-
|
|
1837
|
+
url=args.url,
|
|
1838
|
+
apikey=args.apikey,
|
|
1839
|
+
output=args.output,
|
|
1506
1840
|
debug=args.debug,
|
|
1507
1841
|
trace=args.trace,
|
|
1508
1842
|
quiet=args.quiet,
|
|
1509
1843
|
)
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1844
|
+
success = dt_exporter.upload_sbom_file(args.input, args.project_id, args.project_name,
|
|
1845
|
+
args.project_version, args.output)
|
|
1513
1846
|
if not success:
|
|
1514
1847
|
sys.exit(1)
|
|
1515
|
-
|
|
1516
1848
|
except Exception as e:
|
|
1517
1849
|
print_stderr(f'ERROR: {e}')
|
|
1518
1850
|
if args.debug:
|
|
1519
1851
|
traceback.print_exc()
|
|
1520
1852
|
sys.exit(1)
|
|
1521
1853
|
|
|
1854
|
+
def _dt_args_validator(parser, args):
|
|
1855
|
+
"""
|
|
1856
|
+
Validates command-line arguments related to project identification.
|
|
1857
|
+
|
|
1858
|
+
Parameters
|
|
1859
|
+
----------
|
|
1860
|
+
parser : argparse.ArgumentParser
|
|
1861
|
+
An argument parser instance for handling command-line arguments.
|
|
1862
|
+
args : argparse.Namespace
|
|
1863
|
+
Parsed arguments from the command line containing project-related information.
|
|
1864
|
+
|
|
1865
|
+
Raises
|
|
1866
|
+
------
|
|
1867
|
+
SystemExit
|
|
1868
|
+
If neither a project ID nor the required combination of project name and
|
|
1869
|
+
project version is provided, or if any of the compulsory arguments
|
|
1870
|
+
are missing.
|
|
1871
|
+
"""
|
|
1872
|
+
if not args.project_id and not args.project_name and not args.project_version:
|
|
1873
|
+
print_stderr(
|
|
1874
|
+
'Please specify either a project ID (--project-id) or a project name (--project-name) and '
|
|
1875
|
+
'version (--project-version)'
|
|
1876
|
+
)
|
|
1877
|
+
parser.parse_args([args.subparser, '-h'])
|
|
1878
|
+
sys.exit(1)
|
|
1879
|
+
if not args.project_id and (not args.project_name or not args.project_version):
|
|
1880
|
+
print_stderr('Please supply a project name (--project-name) and version (--project-version)')
|
|
1881
|
+
sys.exit(1)
|
|
1522
1882
|
|
|
1523
1883
|
def utils_certloc(*_):
|
|
1524
1884
|
"""
|
|
@@ -2123,7 +2483,31 @@ def get_scanoss_settings_from_args(args):
|
|
|
2123
2483
|
except ScanossSettingsError as e:
|
|
2124
2484
|
print_stderr(f'Error: {e}')
|
|
2125
2485
|
sys.exit(1)
|
|
2126
|
-
|
|
2486
|
+
return scanoss_settings
|
|
2487
|
+
|
|
2488
|
+
|
|
2489
|
+
def initialise_empty_file(filename: str):
|
|
2490
|
+
"""
|
|
2491
|
+
Initialises an empty file with the specified name. If the file already exists,
|
|
2492
|
+
it truncates its content. Ensures proper error handling in case of failure.
|
|
2493
|
+
|
|
2494
|
+
Args:
|
|
2495
|
+
filename (str): The name of the file to be initialised.
|
|
2496
|
+
|
|
2497
|
+
Raises:
|
|
2498
|
+
SystemExit: If the file cannot be created or written due to an exception,
|
|
2499
|
+
the function prints an error message and exits the program.
|
|
2500
|
+
|
|
2501
|
+
Note:
|
|
2502
|
+
This function writes an empty file and handles exceptions to ensure the
|
|
2503
|
+
program does not continue execution in case of an error.
|
|
2504
|
+
"""
|
|
2505
|
+
if filename:
|
|
2506
|
+
try:
|
|
2507
|
+
open(filename, 'w').close()
|
|
2508
|
+
except Exception as e:
|
|
2509
|
+
print_stderr(f'Error: Unable to create output file {filename}: {e}')
|
|
2510
|
+
sys.exit(1)
|
|
2127
2511
|
|
|
2128
2512
|
|
|
2129
2513
|
def main():
|