def __init__(self, poetry_lock_contents: str) -> None: super().__init__() poetry_lock = load_toml(poetry_lock_contents) for package in poetry_lock['package']: component = Component(name=package['name'], version=package['version'], purl=PackageURL(type='pypi', name=package['name'], version=package['version'])) for file_metadata in poetry_lock['metadata']['files'][ package['name']]: try: component.add_external_reference( ExternalReference( reference_type=ExternalReferenceType.DISTRIBUTION, url=component.get_pypi_url(), comment= f'Distribution file: {file_metadata["file"]}', hashes=[ HashType.from_composite_str( file_metadata['hash']) ])) except UnknownHashTypeException: # @todo add logging for this type of exception? pass self._components.append(component)
def __init__(self, pipenv_contents: str) -> None: super().__init__() pipfile_lock_contents = json.loads(pipenv_contents) pipfile_default: Dict[str, Dict[ str, Any]] = pipfile_lock_contents.get('default') or {} for (package_name, package_data) in pipfile_default.items(): c = Component(name=package_name, version=str( package_data.get('version') or 'unknown').lstrip('='), purl=PackageURL(type='pypi', name=package_name, version=str( package_data.get('version') or 'unknown').lstrip('='))) if package_data.get('index') == 'pypi' and isinstance( package_data.get('hashes'), list): # Add download location with hashes stored in Pipfile.lock for pip_hash in package_data['hashes']: ext_ref = ExternalReference( reference_type=ExternalReferenceType.DISTRIBUTION, url=c.get_pypi_url(), comment='Distribution available from pypi.org') ext_ref.add_hash(HashType.from_composite_str(pip_hash)) c.add_external_reference(ext_ref) self._components.append(c)
def __init__(self) -> None: super().__init__() import pkg_resources i: DistInfoDistribution for i in iter(pkg_resources.working_set): c = Component(name=i.project_name, version=i.version, purl=PackageURL( type='pypi', name=i.project_name, version=i.version )) i_metadata = self._get_metadata_for_package(i.project_name) if 'Author' in i_metadata: c.author = i_metadata['Author'] if 'License' in i_metadata and i_metadata['License'] != 'UNKNOWN': c.licenses.append( LicenseChoice(license_expression=i_metadata['License']) ) if 'Classifier' in i_metadata: for classifier in i_metadata['Classifier']: if str(classifier).startswith('License :: OSI Approved :: '): c.licenses.append( LicenseChoice( license_expression=str(classifier).replace('License :: OSI Approved :: ', '').strip() ) ) self._components.append(c)
def get_cyclonedx_bom(self) -> Bom: bom = Bom() if sys.version_info >= (3, 8, 0): from importlib.metadata import version as meta_version else: from importlib_metadata import version as meta_version try: this_tool = Tool(vendor='bridgecrew', name='checkov', version=meta_version('checkov')) except Exception: # Unable to determine current version of 'checkov' this_tool = Tool(vendor='bridgecrew', name='checkov', version='UNKNOWN') bom.get_metadata().add_tool(this_tool) for check in itertools.chain(self.passed_checks, self.skipped_checks): component = Component.for_file( absolute_file_path=check.file_abs_path, path_for_bom=check.file_path) if bom.has_component(component=component): component = bom.get_component_by_purl( purl=component.get_purl()) bom.add_component(component=component) for failed_check in self.failed_checks: component = Component.for_file( absolute_file_path=failed_check.file_abs_path, path_for_bom=failed_check.file_path) if bom.has_component(component=component): component = bom.get_component_by_purl( purl=component.get_purl()) component.add_vulnerability( Vulnerability( id=failed_check.check_id, source_name='checkov', description= f'Resource: {failed_check.resource}. {failed_check.check_name}', recommendations=[failed_check.guideline])) bom.add_component(component=component) return bom
def __init__(self, requirements_content: str) -> None: super().__init__() requirements = parse_requirements(requirements_content) for requirement in requirements: """ @todo Note that the below line will get the first (lowest) version specified in the Requirement and ignore the operator (it might not be ==). This is passed to the Component. For example if a requirement was listed as: "PickyThing>1.6,<=1.9,!=1.8.6", we'll be interpreting this as if it were written "PickyThing==1.6" """ try: (op, version) = requirement.specs[0] self._components.append(Component( name=requirement.project_name, version=version, purl=PackageURL( type='pypi', name=requirement.project_name, version=version ) )) except IndexError: self._warnings.append( ParserWarning( item=requirement.project_name, warning='Requirement \'{}\' does not have a pinned version and cannot be included in your ' 'CycloneDX SBOM.'.format(requirement.project_name) ) )
def _conda_packages_to_components(self) -> None: """ Converts the parsed `CondaPackage` instances into `Component` instances. """ for conda_package in self._conda_packages: c = Component( name=conda_package['name'], version=str(conda_package['version']), purl=PackageURL( type='pypi', name=conda_package['name'], version=str(conda_package['version']) ) ) c.add_external_reference(ExternalReference( reference_type=ExternalReferenceType.DISTRIBUTION, url=conda_package['base_url'], comment=f"Distribution name {conda_package['dist_name']}" )) self._components.append(c)
def report_to_cyclonedx(report: Report) -> Bom: bom = Bom() for failed_check in report.failed_checks: component = Component.for_file( absolute_file_path=failed_check.file_abs_path, path_for_bom=failed_check.file_path) component.add_vulnerability( Vulnerability( id=failed_check.check_id, source_name='checkov', description= f'Resource: {failed_check.resource}. {failed_check.check_name}', recommendations=[failed_check.guideline])) bom.add_component(component=component) return bom
def add_project( self, project: ProjectEntry, license_name: str, version: str ) -> None: """Add a project to the report.""" match = self.github_url.search(project.remote_url) if match: component = Component( name=project.name, version=version, component_type=ComponentType.LIBRARY, purl=PackageURL( type="github", name=match.group("repo"), version=version, namespace=match.group("group"), subpath=project.source or None, ), ) else: parts = self._split_url(project.remote_url) component = Component( name=project.name, version=version, component_type=ComponentType.LIBRARY, purl=PackageURL( type="generic", version=version, qualifiers=f"download_url={project.remote_url}", namespace=parts[0], subpath=project.source or None, ), ) component.add_external_reference( ExternalReference( reference_type=ExternalReferenceType.VCS, url=project.remote_url, ) ) component.licenses += [LicenseChoice(license_expression=license_name)] self._bom.add_component(component)