conviso-ast 3.0.0__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.
Files changed (128) hide show
  1. conviso_ast-3.0.0.data/scripts/flow_bash_completer.sh +21 -0
  2. conviso_ast-3.0.0.data/scripts/flow_fish_completer.fish +1 -0
  3. conviso_ast-3.0.0.data/scripts/flow_zsh_completer.sh +32 -0
  4. conviso_ast-3.0.0.dist-info/METADATA +37 -0
  5. conviso_ast-3.0.0.dist-info/RECORD +128 -0
  6. conviso_ast-3.0.0.dist-info/WHEEL +5 -0
  7. conviso_ast-3.0.0.dist-info/entry_points.txt +3 -0
  8. conviso_ast-3.0.0.dist-info/top_level.txt +1 -0
  9. convisoappsec/__init__.py +0 -0
  10. convisoappsec/common/__init__.py +5 -0
  11. convisoappsec/common/box.py +251 -0
  12. convisoappsec/common/cleaner.py +78 -0
  13. convisoappsec/common/docker.py +399 -0
  14. convisoappsec/common/exceptions.py +8 -0
  15. convisoappsec/common/git_data_parser.py +76 -0
  16. convisoappsec/common/graphql/__init__.py +0 -0
  17. convisoappsec/common/graphql/error_handlers.py +75 -0
  18. convisoappsec/common/graphql/errors.py +16 -0
  19. convisoappsec/common/graphql/low_client.py +51 -0
  20. convisoappsec/common/retry_handler.py +40 -0
  21. convisoappsec/common/strings.py +8 -0
  22. convisoappsec/flow/__init__.py +3 -0
  23. convisoappsec/flow/api.py +104 -0
  24. convisoappsec/flow/cleaner.py +118 -0
  25. convisoappsec/flow/graphql_api/__init__.py +0 -0
  26. convisoappsec/flow/graphql_api/beta/__init__.py +0 -0
  27. convisoappsec/flow/graphql_api/beta/client.py +18 -0
  28. convisoappsec/flow/graphql_api/beta/models/__init__.py +0 -0
  29. convisoappsec/flow/graphql_api/beta/models/issues/__init__.py +0 -0
  30. convisoappsec/flow/graphql_api/beta/models/issues/container.py +72 -0
  31. convisoappsec/flow/graphql_api/beta/models/issues/iac.py +6 -0
  32. convisoappsec/flow/graphql_api/beta/models/issues/normalize.py +13 -0
  33. convisoappsec/flow/graphql_api/beta/models/issues/sast.py +53 -0
  34. convisoappsec/flow/graphql_api/beta/models/issues/sca.py +78 -0
  35. convisoappsec/flow/graphql_api/beta/resources_api.py +142 -0
  36. convisoappsec/flow/graphql_api/beta/schemas/__init__.py +0 -0
  37. convisoappsec/flow/graphql_api/beta/schemas/mutations/__init__.py +61 -0
  38. convisoappsec/flow/graphql_api/beta/schemas/resolvers/__init__.py +0 -0
  39. convisoappsec/flow/graphql_api/v1/__init__.py +0 -0
  40. convisoappsec/flow/graphql_api/v1/client.py +46 -0
  41. convisoappsec/flow/graphql_api/v1/models/__init__.py +0 -0
  42. convisoappsec/flow/graphql_api/v1/models/asset.py +14 -0
  43. convisoappsec/flow/graphql_api/v1/models/issues.py +16 -0
  44. convisoappsec/flow/graphql_api/v1/models/project.py +35 -0
  45. convisoappsec/flow/graphql_api/v1/resources_api.py +489 -0
  46. convisoappsec/flow/graphql_api/v1/schemas/__init__.py +0 -0
  47. convisoappsec/flow/graphql_api/v1/schemas/mutations/__init__.py +212 -0
  48. convisoappsec/flow/graphql_api/v1/schemas/resolvers/__init__.py +180 -0
  49. convisoappsec/flow/source_code_scanner/__init__.py +9 -0
  50. convisoappsec/flow/source_code_scanner/exceptions.py +2 -0
  51. convisoappsec/flow/source_code_scanner/scc.py +68 -0
  52. convisoappsec/flow/source_code_scanner/source_code_scanner.py +177 -0
  53. convisoappsec/flow/util/__init__.py +7 -0
  54. convisoappsec/flow/util/ci_provider.py +99 -0
  55. convisoappsec/flow/util/metrics.py +16 -0
  56. convisoappsec/flow/util/source_code_compressor.py +22 -0
  57. convisoappsec/flow/version_control_system_adapter.py +528 -0
  58. convisoappsec/flow/version_searchers/__init__.py +9 -0
  59. convisoappsec/flow/version_searchers/sorted_by_versioning_style.py +85 -0
  60. convisoappsec/flow/version_searchers/timebased_version_seacher.py +39 -0
  61. convisoappsec/flow/version_searchers/version_searcher_result.py +33 -0
  62. convisoappsec/flow/versioning_style/__init__.py +0 -0
  63. convisoappsec/flow/versioning_style/semantic_versioning.py +44 -0
  64. convisoappsec/flowcli/__init__.py +3 -0
  65. convisoappsec/flowcli/__main__.py +4 -0
  66. convisoappsec/flowcli/assets/__init__.py +4 -0
  67. convisoappsec/flowcli/assets/create.py +88 -0
  68. convisoappsec/flowcli/assets/entrypoint.py +20 -0
  69. convisoappsec/flowcli/assets/ls.py +63 -0
  70. convisoappsec/flowcli/ast/__init__.py +3 -0
  71. convisoappsec/flowcli/ast/entrypoint.py +427 -0
  72. convisoappsec/flowcli/common.py +175 -0
  73. convisoappsec/flowcli/companies/__init__.py +0 -0
  74. convisoappsec/flowcli/companies/ls.py +25 -0
  75. convisoappsec/flowcli/container/__init__.py +3 -0
  76. convisoappsec/flowcli/container/entrypoint.py +17 -0
  77. convisoappsec/flowcli/container/run.py +306 -0
  78. convisoappsec/flowcli/context.py +49 -0
  79. convisoappsec/flowcli/deploy/__init__.py +0 -0
  80. convisoappsec/flowcli/deploy/create/__init__.py +4 -0
  81. convisoappsec/flowcli/deploy/create/context.py +12 -0
  82. convisoappsec/flowcli/deploy/create/entrypoint.py +31 -0
  83. convisoappsec/flowcli/deploy/create/with_/__init__.py +3 -0
  84. convisoappsec/flowcli/deploy/create/with_/entrypoint.py +20 -0
  85. convisoappsec/flowcli/deploy/create/with_/tag_tracker/__init__.py +4 -0
  86. convisoappsec/flowcli/deploy/create/with_/tag_tracker/context.py +11 -0
  87. convisoappsec/flowcli/deploy/create/with_/tag_tracker/entrypoint.py +30 -0
  88. convisoappsec/flowcli/deploy/create/with_/tag_tracker/sort_by/__init__.py +4 -0
  89. convisoappsec/flowcli/deploy/create/with_/tag_tracker/sort_by/entrypoint.py +21 -0
  90. convisoappsec/flowcli/deploy/create/with_/tag_tracker/sort_by/time_.py +84 -0
  91. convisoappsec/flowcli/deploy/create/with_/tag_tracker/sort_by/versioning_style.py +115 -0
  92. convisoappsec/flowcli/deploy/create/with_/values.py +133 -0
  93. convisoappsec/flowcli/entrypoint.py +103 -0
  94. convisoappsec/flowcli/environment_checker.py +45 -0
  95. convisoappsec/flowcli/findings/__init__.py +4 -0
  96. convisoappsec/flowcli/findings/create/__init__.py +4 -0
  97. convisoappsec/flowcli/findings/create/entrypoint.py +18 -0
  98. convisoappsec/flowcli/findings/create/with_/__init__.py +3 -0
  99. convisoappsec/flowcli/findings/create/with_/entrypoint.py +19 -0
  100. convisoappsec/flowcli/findings/create/with_/version_tracker.py +93 -0
  101. convisoappsec/flowcli/findings/entrypoint.py +19 -0
  102. convisoappsec/flowcli/findings/import_sarif/__init__.py +4 -0
  103. convisoappsec/flowcli/findings/import_sarif/entrypoint.py +430 -0
  104. convisoappsec/flowcli/help_option.py +18 -0
  105. convisoappsec/flowcli/iac/__init__.py +3 -0
  106. convisoappsec/flowcli/iac/entrypoint.py +17 -0
  107. convisoappsec/flowcli/iac/run.py +328 -0
  108. convisoappsec/flowcli/requirements_verifier.py +132 -0
  109. convisoappsec/flowcli/sast/__init__.py +3 -0
  110. convisoappsec/flowcli/sast/entrypoint.py +17 -0
  111. convisoappsec/flowcli/sast/run.py +485 -0
  112. convisoappsec/flowcli/sbom/__init__.py +3 -0
  113. convisoappsec/flowcli/sbom/entrypoint.py +17 -0
  114. convisoappsec/flowcli/sbom/generate.py +235 -0
  115. convisoappsec/flowcli/sca/__init__.py +3 -0
  116. convisoappsec/flowcli/sca/entrypoint.py +17 -0
  117. convisoappsec/flowcli/sca/run.py +479 -0
  118. convisoappsec/flowcli/vulnerability/__init__.py +3 -0
  119. convisoappsec/flowcli/vulnerability/assert_security_rules.py +201 -0
  120. convisoappsec/flowcli/vulnerability/container_vulnerability_manager.py +175 -0
  121. convisoappsec/flowcli/vulnerability/entrypoint.py +18 -0
  122. convisoappsec/flowcli/vulnerability/rules_schema.json +53 -0
  123. convisoappsec/flowcli/vulnerability/run.py +487 -0
  124. convisoappsec/logger.py +29 -0
  125. convisoappsec/sast/__init__.py +0 -0
  126. convisoappsec/sast/decision.py +45 -0
  127. convisoappsec/sast/sastbox.py +296 -0
  128. convisoappsec/version.py +1 -0
@@ -0,0 +1,115 @@
1
+ import click
2
+ # TODO: refactoring. all deploy create share some behavior
3
+ from convisoappsec.flow.util import project_metrics
4
+ from convisoappsec.flowcli.context import pass_flow_context
5
+ from convisoappsec.flow.version_searchers import SortedByVersioningStyle
6
+ from convisoappsec.flow.version_control_system_adapter import GitAdapter
7
+ from convisoappsec.flowcli import help_option
8
+ from convisoappsec.flowcli.common import on_http_error
9
+ from convisoappsec.flowcli.deploy.create.context import pass_create_context
10
+
11
+ from convisoappsec.flowcli.deploy.create.with_.tag_tracker.context import (
12
+ pass_tag_tracker_context
13
+ )
14
+
15
+
16
+ @click.command()
17
+ @click.option(
18
+ '-c',
19
+ '--current-tag',
20
+ required=False,
21
+ help="""This value is used to ignore versions
22
+ bigger than this value if exists"""
23
+ )
24
+ @click.option(
25
+ '-i',
26
+ '--ignore-prefix',
27
+ required=False,
28
+ default='v',
29
+ show_default=True,
30
+ help="Prefix to be ignored on parsing to versioning style.",
31
+ )
32
+ @click.option(
33
+ '-s',
34
+ '--style',
35
+ required=False,
36
+ type=click.Choice(SortedByVersioningStyle.STYLES),
37
+ default=SortedByVersioningStyle.SEMANTIC_VERSIONING_STYLE,
38
+ show_default=True,
39
+ help="Versioning style type used at repository.",
40
+ )
41
+ @click.option(
42
+ "--attach-diff/--no-attach-diff",
43
+ default=True,
44
+ show_default=True,
45
+ required=False,
46
+ )
47
+ @help_option
48
+ @pass_tag_tracker_context
49
+ @pass_create_context
50
+ @pass_flow_context
51
+ def versioning_style(
52
+ flow_context, create_context, tag_tracker_context, ignore_prefix, style,
53
+ current_tag, attach_diff
54
+ ):
55
+ try:
56
+ repository_dir = tag_tracker_context.repository_dir
57
+ git_adapter = GitAdapter(repository_dir)
58
+
59
+ searcher = SortedByVersioningStyle(
60
+ git_adapter,
61
+ ignore_prefix,
62
+ style,
63
+ current_tag,
64
+ )
65
+
66
+ result = searcher.find_current_and_previous_version()
67
+ current_version = result.current_version
68
+ previous_version = result.previous_version
69
+ diff_content = None
70
+
71
+ current_commit = current_version.get('commit')
72
+ previous_commit = previous_version.get('commit')
73
+
74
+ if previous_commit == current_commit:
75
+ import sys
76
+ click.echo(
77
+ "Previous commit ({0}) and Current commit ({1}) are the same, nothing to do.".format(
78
+ previous_commit, current_commit
79
+ ),
80
+ file=sys.stderr
81
+ )
82
+ return
83
+
84
+ if attach_diff:
85
+ diff_content = git_adapter.diff(
86
+ previous_commit,
87
+ current_commit,
88
+ )
89
+
90
+ deploy_metrics = git_adapter.diff_stats(
91
+ previous_commit,
92
+ current_commit,
93
+ ).dict
94
+
95
+ flow = flow_context.create_conviso_rest_api_client()
96
+
97
+ authors_data = git_adapter.get_commit_authors_by_range(
98
+ previous_commit, current_commit
99
+ )
100
+
101
+ deploy = flow.deploys.create(
102
+ current_version=current_version,
103
+ previous_version=previous_version,
104
+ diff_content=diff_content,
105
+ metrics=deploy_metrics,
106
+ project_metrics=project_metrics(repository_dir),
107
+ commit_authors=authors_data
108
+ )
109
+
110
+ click.echo(
111
+ create_context.output_formatter.format(deploy)
112
+ )
113
+ except Exception as e:
114
+ on_http_error(e)
115
+ raise click.ClickException(str(e)) from e
@@ -0,0 +1,133 @@
1
+ import click
2
+ import git
3
+ import time
4
+ import json
5
+ import tempfile
6
+ import traceback
7
+ from convisoappsec.flowcli.context import pass_flow_context
8
+ from convisoappsec.flowcli import help_option
9
+ from convisoappsec.flow import GitAdapter
10
+ from convisoappsec.flowcli.common import on_http_error
11
+ from convisoappsec.logger import LOGGER
12
+
13
+ class SameCommitException(Exception):
14
+ pass
15
+
16
+
17
+ @click.command()
18
+ @help_option
19
+ @click.option(
20
+ "-c",
21
+ "--current-commit",
22
+ required=False,
23
+ help="If no value is given the HEAD commit of branch is used.",
24
+ )
25
+ @click.option(
26
+ "-p",
27
+ "--previous-commit",
28
+ required=False,
29
+ help="""If no value is given, the value is retrieved from the lastest
30
+ deploy at flow application.""",
31
+ )
32
+ @click.option(
33
+ "-r",
34
+ "--repository-dir",
35
+ required=False,
36
+ type=click.Path(exists=True, resolve_path=True),
37
+ default='.',
38
+ show_default=True,
39
+ help="Repository directory.",
40
+ )
41
+ @click.option(
42
+ "--asset-id",
43
+ required=False,
44
+ envvar=("CONVISO_ASSET_ID", "FLOW_ASSET_ID"),
45
+ help="Asset ID on Conviso Platform",
46
+ )
47
+ @click.pass_context
48
+ def values(context, repository_dir, current_commit, previous_commit, asset_id):
49
+ try:
50
+ if context.params['asset_id'] is not None and asset_id is None:
51
+ asset_id = context.params['asset_id']
52
+
53
+ git_adapter = GitAdapter(repository_dir)
54
+ commits = deploys_from_asset(asset_id=asset_id)
55
+ current_commit = current_commit or git_adapter.head_commit
56
+ last_commit = commits[0]['currentCommit'] if commits else git_adapter.empty_repository_tree_commit
57
+
58
+ if last_commit == current_commit:
59
+ raise SameCommitException(
60
+ "Previous commit ({0}) and Current commit ({1}) are the same, nothing to do."
61
+ .format(last_commit, current_commit)
62
+ )
63
+
64
+ if not previous_commit:
65
+ previous_commit = commits[0]['currentCommit'] if commits else git_adapter.empty_repository_tree_commit
66
+
67
+ if previous_commit != '4b825dc642cb6eb9a060e54bf8d69288fbee4904':
68
+ try:
69
+ git_adapter._repo.commit(previous_commit)
70
+ except (git.exc.BadName, ValueError):
71
+ commits = deploys_from_asset(asset_id=asset_id)
72
+ previous_commit = None
73
+
74
+ for commit in commits:
75
+ commit_hash = commit['currentCommit']
76
+ try:
77
+ git_adapter._repo.commit(commit_hash)
78
+ previous_commit = commit_hash
79
+ break
80
+ except (git.exc.BadName, ValueError):
81
+ continue
82
+
83
+ if previous_commit is None:
84
+ previous_commit = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'
85
+
86
+ commit_history_list = git_adapter.get_commit_history()
87
+
88
+ commit_history_file = tempfile.NamedTemporaryFile(mode='w+', delete=False)
89
+ json.dump(commit_history_list, commit_history_file)
90
+ commit_history_file.seek(0)
91
+
92
+ return {
93
+ "previous_commit": previous_commit,
94
+ "current_commit": current_commit,
95
+ "commit_history": commit_history_file.name,
96
+ }
97
+
98
+ except SameCommitException as e:
99
+ LOGGER.warning(str(e))
100
+
101
+ return None
102
+
103
+ except git.exc.GitError as e:
104
+ LOGGER.error(f"Git error: {str(e)}")
105
+ raise click.ClickException(f"Git error: {str(e)}") from e
106
+
107
+ except Exception as e:
108
+ if "GraphqlController" in str(e):
109
+ LOGGER.error(f"GraphQL API error: {str(e)}")
110
+ raise click.ClickException(f"Error communicating with Conviso API: {str(e)}") from e
111
+
112
+ LOGGER.warning("There was an error. Our team has been notified.")
113
+ full_trace = traceback.format_exc()
114
+ LOGGER.error(full_trace)
115
+ on_http_error(e)
116
+ raise click.ClickException(str(e)) from e
117
+
118
+ @pass_flow_context
119
+ def deploys_from_asset(flow_context, asset_id, max_retries=3):
120
+ """ Returns all deploys from an asset with retry logic """
121
+ for attempt in range(max_retries):
122
+ try:
123
+ conviso_api = flow_context.create_conviso_graphql_client()
124
+ deploys = conviso_api.deploys.get_deploys_by_asset(asset_id=asset_id)
125
+
126
+ return deploys
127
+ except Exception as e:
128
+ if attempt == max_retries - 1:
129
+ LOGGER.error(f"Failed to fetch deploys for asset {asset_id} after {max_retries} attempts: {str(e)}")
130
+ raise
131
+ LOGGER.warning(f"Attempt {attempt + 1} failed: {str(e)}. Retrying...")
132
+ time.sleep(2 ** attempt)
133
+ return None
@@ -0,0 +1,103 @@
1
+ import os
2
+
3
+ import click
4
+ import click_log
5
+ from convisoappsec.flow import api
6
+ from convisoappsec.flow.util.ci_provider import CIProvider
7
+ from convisoappsec.flowcli import help_option
8
+ from convisoappsec.flowcli.common import process_ci_provider_option
9
+ from convisoappsec.flowcli.iac.entrypoint import iac
10
+ from convisoappsec.logger import LOGGER
11
+ from convisoappsec.version import __version__
12
+
13
+ from .ast import ast
14
+ from .context import pass_flow_context
15
+ from .findings import findings
16
+ from .sast import sast
17
+ from .sca import sca
18
+ from .vulnerability import vulnerability
19
+ from .assets import assets
20
+ from .sbom import sbom
21
+ from .container import container
22
+
23
+ click_log.basic_config(LOGGER)
24
+
25
+ @click.group()
26
+ @click_log.simple_verbosity_option(LOGGER, '-l', '--verbosity')
27
+ @click.option(
28
+ '-k',
29
+ '--api-key',
30
+ show_envvar=True,
31
+ envvar=("CONVISO_API_KEY", "FLOW_API_KEY"),
32
+ help="The api key to access Conviso Platform resources.",
33
+ )
34
+ @click.option(
35
+ '-u',
36
+ '--api-url',
37
+ show_envvar=True,
38
+ envvar=("CONVISO_API_URL", "FLOW_API_URL"),
39
+ default=api.DEFAULT_API_URL,
40
+ show_default=True,
41
+ help='The api url to access Conviso Platform resources.',
42
+ )
43
+ @click.option(
44
+ '-i',
45
+ '--api-insecure',
46
+ show_envvar=True,
47
+ envvar=("CONVISO_API_INSECURE", "FLOW_API_INSECURE"),
48
+ default=False,
49
+ show_default=True,
50
+ is_flag=True,
51
+ help='HTTPS requests to untrusted hosts is enable.',
52
+ )
53
+ @click.option(
54
+ '-c',
55
+ '--ci-provider-name',
56
+ show_envvar=True,
57
+ envvar="CI_PROVIDER_NAME",
58
+ type=click.Choice(CIProvider.names()),
59
+ default=None,
60
+ show_default=True,
61
+ required=False,
62
+ help="The ci provider used by project. "
63
+ "When not informed, an automatic search will be performed."
64
+ )
65
+ @click.option(
66
+ '--experimental',
67
+ default=False,
68
+ is_flag=True,
69
+ hidden=True,
70
+ help="Enable experimental features.",
71
+ )
72
+ @help_option
73
+ @click.version_option(
74
+ __version__,
75
+ '-v',
76
+ '--version',
77
+ message='%(prog)s %(version)s'
78
+ )
79
+ @pass_flow_context
80
+ def cli(flow_context, api_key, api_url, api_insecure, experimental, ci_provider_name):
81
+ flow_context.key = api_key
82
+ flow_context.url = api_url
83
+ flow_context.insecure = api_insecure
84
+ flow_context.experimental = experimental
85
+
86
+ ci_provider = process_ci_provider_option(ci_provider_name, os.environ)
87
+ flow_context.ci_provider = ci_provider
88
+ LOGGER.debug('CI provider name detected: {}'.format(flow_context.ci_provider.name))
89
+
90
+
91
+ cli.add_command(findings)
92
+ cli.add_command(sast)
93
+ cli.add_command(sca)
94
+ cli.add_command(vulnerability)
95
+ cli.add_command(ast)
96
+ cli.add_command(iac)
97
+ cli.add_command(assets)
98
+ cli.add_command(sbom)
99
+ cli.add_command(container)
100
+
101
+ cli.epilog = '''
102
+ Run conviso COMMAND --help for more information on a command.
103
+ '''
@@ -0,0 +1,45 @@
1
+ import os
2
+ import platform
3
+ import subprocess
4
+
5
+ class EnvironmentChecker:
6
+ """
7
+ A class to check the system environment for required software and services.
8
+ """
9
+
10
+ def __init__(self):
11
+ self.checks = {}
12
+
13
+ def _run_command(self, command, check_running=False):
14
+ """Helper function to run shell commands and capture output/errors."""
15
+ try:
16
+ process = subprocess.run(command, capture_output=True, text=True, check=not check_running)
17
+ if check_running:
18
+ return process.returncode == 0, "", ""
19
+ return process.returncode == 0, process.stdout.strip(), process.stderr.strip()
20
+ except FileNotFoundError:
21
+ return False, "", "Command not found"
22
+ except subprocess.CalledProcessError as e:
23
+ return False, "", e.stderr.strip()
24
+
25
+ def check_docker(self):
26
+ """Checks if Docker is installed and the daemon is running."""
27
+ installed, _, _ = self._run_command(["docker", "--version"])
28
+ running, _, _ = self._run_command(["docker", "info"], check_running=True)
29
+ self.checks["docker_installed"] = installed
30
+ self.checks["docker_running"] = running
31
+ return installed and running
32
+
33
+ def run_all_checks(self):
34
+ """Runs all checks and prints a summary."""
35
+ self.check_docker()
36
+
37
+ print("Environment Check Summary:")
38
+ for check, result in self.checks.items():
39
+ if "version" in check:
40
+ print(f"- {check.replace('_',' ').title()}: {result}")
41
+ else:
42
+ status = "OK" if result else "FAILED"
43
+ print(f"- {check.replace('_',' ').title()}: {status}")
44
+
45
+ return all(self.checks.values())
@@ -0,0 +1,4 @@
1
+ from .entrypoint import findings
2
+
3
+
4
+ __all__ = ['findings']
@@ -0,0 +1,4 @@
1
+ from .entrypoint import create
2
+
3
+
4
+ __all__ = ['create']
@@ -0,0 +1,18 @@
1
+ import click
2
+
3
+ from convisoappsec.flowcli import help_option
4
+
5
+ from .with_ import with_
6
+
7
+
8
+ @click.group()
9
+ @help_option
10
+ def create():
11
+ pass
12
+
13
+
14
+ create.add_command(with_)
15
+
16
+ create.epilog = '''
17
+ Run flow findings create COMMAND --help for more information on a command.
18
+ '''
@@ -0,0 +1,3 @@
1
+ from .entrypoint import with_
2
+
3
+ __all__ = ['with_']
@@ -0,0 +1,19 @@
1
+ import click
2
+
3
+ from convisoappsec.flowcli import help_option
4
+
5
+ from .version_tracker import version_tracker
6
+
7
+
8
+ @click.group('with')
9
+ @help_option
10
+ def with_():
11
+ pass
12
+
13
+
14
+ with_.add_command(version_tracker)
15
+
16
+ with_.epilog = '''
17
+ Run flow findings create with COMMAND --help for more information
18
+ on a command.
19
+ '''
@@ -0,0 +1,93 @@
1
+ import click
2
+ from pathlib import Path
3
+
4
+ from convisoappsec.flow.version_control_system_adapter import GitAdapter
5
+ from convisoappsec.flowcli.context import pass_flow_context
6
+ from convisoappsec.flowcli import help_option
7
+
8
+
9
+ def finding_report_files_validation(_, __, finding_report_files):
10
+ allowed_extensions = ['.json']
11
+ allowed_extensions_str = '[{0}]'.format(
12
+ '|'.join(allowed_extensions)
13
+ )
14
+
15
+ for report_file in finding_report_files:
16
+ file_name = report_file.name
17
+
18
+ if Path(file_name).suffix not in allowed_extensions:
19
+ raise click.BadParameter(
20
+ 'Allowed file extensions {0}. File given: {1}'.format(
21
+ allowed_extensions_str,
22
+ file_name
23
+ )
24
+ )
25
+
26
+ return finding_report_files
27
+
28
+
29
+ @click.command()
30
+ @click.argument(
31
+ "finding-report-files",
32
+ nargs=-1,
33
+ required=False,
34
+ type=click.File('r'),
35
+ callback=finding_report_files_validation
36
+ )
37
+ @click.option(
38
+ '-c',
39
+ '--current-commit',
40
+ required=False,
41
+ help="""The hash of current commit. If no value is set
42
+ so the HEAD commit will be used.""",
43
+ )
44
+ @click.option(
45
+ "-r",
46
+ "--repository-dir",
47
+ required=False,
48
+ type=click.Path(exists=True),
49
+ default=".",
50
+ show_default=True,
51
+ help='The root dir of repository.',
52
+ )
53
+ @click.option(
54
+ "-t",
55
+ "--default-report-type",
56
+ required=False,
57
+ help="""This value is used when report type attribute is missing.
58
+ This not override an existing value at report file""",
59
+ )
60
+ @help_option
61
+ @pass_flow_context
62
+ def version_tracker(
63
+ flow_context, finding_report_files,
64
+ repository_dir, current_commit, default_report_type
65
+ ):
66
+ try:
67
+ if not finding_report_files:
68
+ click.echo(
69
+ "Nothing to be done, finding report files argument empty"
70
+ )
71
+
72
+ return
73
+
74
+ git = GitAdapter(repository_dir)
75
+ current_commit = current_commit or git.head_commit
76
+ commit_refs = git.show_commit_refs(current_commit)
77
+ finding_report_files_prog_bar_ctx = click.progressbar(
78
+ finding_report_files,
79
+ label='Sending finding reports'
80
+ )
81
+
82
+ flow = flow_context.create_conviso_rest_api_client()
83
+
84
+ with finding_report_files_prog_bar_ctx as reports_with_progressbar:
85
+ for finding_report in reports_with_progressbar:
86
+ flow.findings.create(
87
+ commit_refs,
88
+ finding_report,
89
+ default_report_type=default_report_type
90
+ )
91
+
92
+ except Exception as e:
93
+ raise click.ClickException(str(e)) from e
@@ -0,0 +1,19 @@
1
+ import click
2
+
3
+ from convisoappsec.flowcli import help_option
4
+ from .create import create
5
+ from .import_sarif import import_sarif
6
+
7
+
8
+ @click.group()
9
+ @help_option
10
+ def findings():
11
+ pass
12
+
13
+
14
+ findings.add_command(create)
15
+ findings.add_command(import_sarif)
16
+
17
+ findings.epilog = '''
18
+ Run flow findings COMMAND --help for more information on a command.
19
+ '''
@@ -0,0 +1,4 @@
1
+ from .entrypoint import import_sarif
2
+
3
+
4
+ __all__ = ['import_sarif']