Beispiel #1
0
    def get(self, ecosystem):
        query = request.args.get('q')
        eco = Ecosystem.by_name(rdb.session, ecosystem)
        fetcher = CucosReleasesFetcher(eco, rdb.session)
        now = datetime.datetime.now()

        # Instantiate two different solvers, one using a custom fetcher to fetch
        # matching releases from Bayesian DB and the other one fetching from
        # upstream repositories.
        # The data from these two solvers then provide information as to:
        #   1) Which packages in the range we have already analysed and have information
        #        about
        #   2) Other packages from upstream repositories which match the version specification
        cucos_solver, solver = get_ecosystem_solver(eco, with_fetcher=fetcher),\
                               get_ecosystem_solver(eco)

        ours = cucos_solver.solve([query], all_versions=True)
        upstream = solver.solve([query], all_versions=True)

        ours_nums = set() if not ours else set(next(iter(ours.values())))
        upstreams_nums = set() if not upstream else set(
            next(iter(upstream.values())))

        return {
            'query': query,
            'detail': {
                'analysed': ours,
                'upstream': upstream,
                'difference': list(upstreams_nums - ours_nums)
            },
            'resolved_at': str(now)
        }
Beispiel #2
0
 def _handle_external_deps(self, ecosystem, deps):
     """Resolve external dependency specifications"""
     if not ecosystem or not deps:
         return []
     solver = get_ecosystem_solver(ecosystem)
     versions = solver.solve(deps)
     return [{"package": k, "version": v} for k, v in versions.items()]
    def _get_versions_to_scan(self, package_name, version_string,
                              only_already_scanned):
        """ Compute versions that should be scanned based on version string

        :param package_name: name of the package which versions should be resolved
        :param version_string: version string for the package
        :param only_already_scanned: if True analyse only packages that were already analysed
        :return: list of versions that should be analysed
        """
        solver = get_ecosystem_solver(self.storage.get_ecosystem('npm'))
        try:
            resolved = solver.solve(
                ["{} {}".format(package_name, version_string)],
                all_versions=True)
        except:
            self.log.exception("Failed to resolve versions for package '%s'",
                               package_name)
            return []

        resolved_versions = resolved.get(package_name, [])

        if only_already_scanned:
            result = []
            for version in resolved_versions:
                if self.storage.get_analysis_count('npm', package_name,
                                                   version) > 0:
                    result.append(version)
            return result
        else:
            return resolved_versions
Beispiel #4
0
    def _resolve_dependency(self, ecosystem, dep):
        ret = {
            'ecosystem': ecosystem.name,
            'declaration': dep,
            'resolved_at': json_serial(datetime.datetime.now())
        }

        # first, if this is a Github dependency, return it right away (we don't resolve these yet)
        if ' ' in dep:
            name, spec = dep.split(' ', 1)
            if gh_dep.match(spec):
                ret['name'] = name
                ret['version'] = 'https://github.com/' + spec
        else:
            if gh_dep.match(dep):
                ret['name'] = 'https://github.com/' + dep
                ret['version'] = None
        if 'name' in ret:
            return ret

        # second, figure out what is the latest upstream version matching the spec and return it
        solver = get_ecosystem_solver(ecosystem)
        pkgspec = solver.solve([dep])

        if not pkgspec:
            raise TaskError("invalid dependency: {}".format(dep))

        package, version = pkgspec.popitem()
        if not version:
            raise TaskError("bad version resolved for {}".format(dep))

        ret['name'] = package
        ret['version'] = version
        return ret
Beispiel #5
0
    def _npm_scan(self, arguments):
        """
        Query Snyk vulndb stored on S3
        """
        s3 = StoragePool.get_connected_storage('S3Snyk')

        try:
            self.log.debug('Retrieving Snyk vulndb from S3')
            vulndb = s3.retrieve_vulndb()
        except:
            self.log.error('Failed to obtain Snyk vulndb database')
            return {'summary': ['Failed to obtain Snyk vulndb database'],
                    'status': 'error',
                    'details': []}

        entries = []
        solver = get_ecosystem_solver(self.storage.get_ecosystem('npm'))
        for entry in vulndb.get('npm', {}).get(arguments['name'], []):
            vulnerable_versions = entry['semver']['vulnerable']
            affected_versions = solver.solve(["{} {}".format(arguments['name'],
                                                             vulnerable_versions)],
                                             all_versions=True)
            if arguments['version'] in affected_versions.get(arguments['name'], []):
                entries.append(self._filter_vulndb_fields(entry))

        return {'summary': [e['id'] for e in entries if e],
                'status': 'success',
                'details': entries}
Beispiel #6
0
    def test_rubygems(self, rubygems):
        solver = get_ecosystem_solver(rubygems)
        deps = [
            "Hoe ~>3.14", "rexicaL >=1.0.5", "raKe-compiler-dock ~>0.4.2",
            "rake-comPiler ~>0.9.2"
        ]
        out = solver.solve(deps)

        assert len(out) == len(deps)
Beispiel #7
0
 def test_npm_solver(self, npm, semver_string, expected):
     solver = get_ecosystem_solver(npm)
     name = 'test_name'
     # mock fetched releases to have predictable results
     flexmock(NpmReleasesFetcher,
              fetch_releases=(name, self.SERVE_STATIC_VER))
     solver_result = solver.solve([name + ' ' + semver_string],
                                  all_versions=True)
     # {'name': ['1.0.0', '1.0.1']}
     assert set(solver_result.get(name, [])) == set(expected)
Beispiel #8
0
    def test_cucos_fetcher(self, rdb, npm):
        # create initial dataset
        package = Package(ecosystem=npm, name='cucos')
        rdb.add(package)
        rdb.commit()
        versions = {
            '0.5.0', '0.5.1', '0.6.0', '0.6.4', '0.7.0', '0.8.0', '0.9.0',
            '1.0.0', '1.0.5'
        }
        for v in versions:
            version = Version(package=package, identifier=v)
            rdb.add(version)
            rdb.commit()
            analysis = Analysis(version=version)
            # Fetcher only selects finished analyses
            analysis.finished_at = datetime.datetime.now()
            rdb.add(analysis)
            rdb.commit()

        f = CucosReleasesFetcher(npm, rdb)

        r = f.fetch_releases('cucos')[1]

        # make sure we fetched the same stuff we inserted
        assert set(r) == versions

        # first should be the latest
        assert r.pop() == '1.0.5'

        # try different dependency specs
        s = get_ecosystem_solver(npm, f)
        assert s.solve(['cucos ^0.5.0'])['cucos'] == '0.5.1'
        assert s.solve(['cucos 0.x.x'])['cucos'] == '0.9.0'
        assert s.solve(['cucos >1.0.0'])['cucos'] == '1.0.5'
        assert s.solve(['cucos ~>0.6.0'])['cucos'] == '0.6.4'

        # check that with `all_versions` we return all the relevant ones
        assert set(s.solve(['cucos >=0.6.0'], all_versions=True)['cucos']) == \
            (versions - {'0.5.0', '0.5.1'})
Beispiel #9
0
    def test_pypi(self, pypi):
        solver = get_ecosystem_solver(pypi)
        deps = ["pymongo>=3.0,<3.2.2", "celery>3.1.11", "six==1.10.0"]
        out = solver.solve(deps)

        assert len(out) == len(deps)
Beispiel #10
0
 def test_maven_solver(self, maven, dependencies, expected):
     solver = get_ecosystem_solver(maven)
     solver_result = solver.solve(dependencies)
     assert len(solver_result) == len(dependencies)
     for name, version in solver_result.items():
         assert expected.get(name, '') == version