示例#1
0
    def get_mythx_client() -> Client:
        """Generate a MythX client instance.

        This method will look for an API key passed as a parameter, and if none
        is found, look for a key in the environment variable :code:`MYTHX_API_KEY`.
        If a key is detected, a PythX client instance is returned, otherwise a
        :code:`ValidationError` is raised.

        :raises: ValidationError if no valid API key is provided
        :return: A PythX client instance
        """

        if CONFIG.argv["api-key"]:
            auth_args = {"api_key": CONFIG.argv["api-key"]}
        elif environ.get("MYTHX_API_KEY"):
            auth_args = {"api_key": environ.get("MYTHX_API_KEY")}
        else:
            raise ValidationError(
                "You must provide a MythX API key via environment variable or the command line"
            )

        return Client(**auth_args,
                      middlewares=[
                          ClientToolNameMiddleware(
                              name=f"brownie-{__version__}")
                      ])
示例#2
0
def main():
    """The main entry point of the MythX plugin for Brownie."""

    args = docopt(__doc__)
    _update_argv_from_docopt(args)

    if CONFIG.argv["mode"] not in ANALYSIS_MODES:
        raise ValidationError(
            "Invalid analysis mode: Must be one of [{}]".format(
                ", ".join(ANALYSIS_MODES)))

    project_path = project.check_for_project(".")
    if project_path is None:
        raise ProjectNotFound

    build = project.load()._build
    submission = SubmissionPipeline(build)

    print("Preparing project data for submission to MythX...")
    submission.prepare_requests()

    print("Sending analysis requests to MythX...")
    submission.send_requests()

    # exit if user wants an async analysis run
    if CONFIG.argv["async"]:
        print(
            "\nAll contracts were submitted successfully. Check the dashboard at "
            "https://dashboard.mythx.io/ for the progress and results of your analyses"
        )
        return

    print("\nWaiting for results...")

    submission.wait_for_jobs()
    submission.generate_stdout_report()
    submission.generate_highlighting_report()

    # erase previous report
    report_path = project_path.joinpath(
        _load_project_structure_config(project_path)["reports"])

    report_path = report_path.joinpath("security.json")
    if report_path.exists():
        report_path.unlink()

    print_console_report(submission.stdout_report)

    # Write report to Brownie directory
    with report_path.open("w+") as fp:
        json.dump(submission.highlight_report, fp, indent=2, sort_keys=True)

    # Launch GUI if user requested it
    if CONFIG.argv["gui"]:
        print("Launching the Brownie GUI")
        gui = importlib.import_module("brownie._gui").Gui
        gui().mainloop()
示例#3
0
    def wait_for_jobs(self) -> None:
        """Poll the MythX API and returns once all requests have been processed.

        This will wait for all analysis requests in the internal :code:`responses`
        dict to finish. If a user passes the :code:`--interval` option, the plugin
        will poll the MythX API in the user-specified interval (in seconds) to see
        whether the analysis request is done processing.

        If the internal responses dict is empty, a :code:`ValidationError` is raised.

        :raise: :code:`ValidationError`
        :return: None
        """

        if not self.responses:
            raise ValidationError("No requests given")
        for contract_name, response in self.responses.items():
            while not self.client.analysis_ready(response.uuid):
                time.sleep(int(CONFIG.argv["interval"]))
            self.reports[contract_name] = self.client.report(response.uuid)