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,328 @@
1
+ import json
2
+ import click
3
+ import click_log
4
+ import traceback
5
+ from convisoappsec.common.retry_handler import RetryHandler
6
+ from copy import deepcopy as clone
7
+ from convisoappsec.common.box import ContainerWrapper
8
+ from convisoappsec.flow.graphql_api.beta.models.issues.iac import CreateIacFindingInput
9
+ from convisoappsec.flowcli import help_option
10
+ from convisoappsec.flowcli.common import asset_id_option, on_http_error
11
+ from convisoappsec.flowcli.context import pass_flow_context
12
+ from convisoappsec.logger import LOGGER, log_and_notify_ast_event
13
+ from convisoappsec.flowcli.requirements_verifier import RequirementsVerifier
14
+ from convisoappsec.flow import GitAdapter
15
+ from convisoappsec.common.graphql.errors import ResponseError
16
+ from convisoappsec.common.cleaner import Cleaner
17
+
18
+ click_log.basic_config(LOGGER)
19
+
20
+
21
+ @click.command()
22
+ @click_log.simple_verbosity_option(LOGGER)
23
+ @asset_id_option(required=False)
24
+ @click.option(
25
+ '-r',
26
+ '--repository-dir',
27
+ default=".",
28
+ show_default=True,
29
+ type=click.Path(
30
+ exists=True,
31
+ resolve_path=True,
32
+ ),
33
+ required=False,
34
+ help="The source code repository directory.",
35
+ )
36
+ @click.option(
37
+ "--send-to-flow/--no-send-to-flow",
38
+ default=True,
39
+ show_default=True,
40
+ required=False,
41
+ help="""Enable or disable the ability of send analysis result
42
+ reports to flow.""",
43
+ hidden=True
44
+ )
45
+ @click.option(
46
+ "--scanner-timeout",
47
+ hidden=True,
48
+ required=False,
49
+ default=7200,
50
+ type=int,
51
+ help="Set timeout for each scanner"
52
+ )
53
+ @click.option(
54
+ "--parallel-workers",
55
+ hidden=True,
56
+ required=False,
57
+ default=2,
58
+ type=int,
59
+ help="Set max parallel workers"
60
+ )
61
+ @click.option(
62
+ "--deploy-id",
63
+ default=None,
64
+ required=False,
65
+ hidden=True,
66
+ envvar=("CONVISO_DEPLOY_ID", "FLOW_DEPLOY_ID")
67
+ )
68
+ @click.option(
69
+ '--experimental',
70
+ default=False,
71
+ is_flag=True,
72
+ hidden=True,
73
+ help="Enable experimental features.",
74
+ )
75
+ @click.option(
76
+ "--company-id",
77
+ required=False,
78
+ envvar=("CONVISO_COMPANY_ID", "FLOW_COMPANY_ID"),
79
+ help="Company ID on Conviso Platform",
80
+ )
81
+ @click.option(
82
+ '--asset-name',
83
+ required=False,
84
+ envvar=("CONVISO_ASSET_NAME", "FLOW_ASSET_NAME"),
85
+ help="Provides a asset name.",
86
+ )
87
+ @click.option(
88
+ '--from-ast',
89
+ default=False,
90
+ is_flag=True,
91
+ hidden=True,
92
+ help="Internal use only.",
93
+ )
94
+ @click.option(
95
+ '--cleanup',
96
+ default=False,
97
+ is_flag=True,
98
+ show_default=True,
99
+ help="Clean up system resources, including temporary files, stopped containers, unused Docker images and volumes.",
100
+ )
101
+ @click.option(
102
+ '--control-sync-status-id',
103
+ required=False,
104
+ hidden=True,
105
+ help="Control sync status id.",
106
+ )
107
+ @click.option(
108
+ '--control-sync-status-id',
109
+ required=False,
110
+ hidden=True,
111
+ help="Control sync status id.",
112
+ )
113
+ @help_option
114
+ @pass_flow_context
115
+ @click.pass_context
116
+ def run(context, flow_context, asset_id, company_id, repository_dir, send_to_flow, scanner_timeout,
117
+ parallel_workers, deploy_id, experimental, asset_name, from_ast, cleanup, control_sync_status_id):
118
+ """
119
+ This command will perform IAC analysis at the source code. The analysis
120
+ results can be reported or not to flow application.
121
+ """
122
+ if not from_ast:
123
+ prepared_context = RequirementsVerifier.prepare_context(clone(context))
124
+
125
+ params_to_copy = [
126
+ 'asset_id', 'company_id', 'repository_dir', 'send_to_flow',
127
+ 'deploy_id', 'scanner_timeout', 'parallel_workers', 'experimental', 'cleanup'
128
+ ]
129
+
130
+ for param_name in params_to_copy:
131
+ context.params[param_name] = (
132
+ locals()[param_name] or prepared_context.params[param_name]
133
+ )
134
+
135
+ perform_command(
136
+ flow_context, context.params['asset_id'], context.params['company_id'], context.params['repository_dir'],
137
+ context.params['send_to_flow'], context.params['scanner_timeout'], context.params['deploy_id'],
138
+ context.params['experimental'], context.params['cleanup'], from_ast, control_sync_status_id
139
+ )
140
+
141
+
142
+ def deploy_results_to_conviso(
143
+ conviso_api, results_filepaths, asset_id, company_id, flow_context, deploy_id, commit_ref=None, control_sync_status_id=None
144
+ ):
145
+ results_context = click.progressbar(results_filepaths, label="Sending results to the Conviso Platform...")
146
+
147
+ with results_context as reports:
148
+ for report_path in reports:
149
+ try:
150
+ with open(report_path) as report_file:
151
+ data = parse_data(json.load(report_file))
152
+ except Exception:
153
+ LOGGER.warn(f"⚠️ Error processing report file. Our technical team has been notified.")
154
+ full_trace = traceback.format_exc()
155
+ log_and_notify_ast_event(
156
+ flow_context=flow_context, company_id=company_id, asset_id=asset_id,
157
+ ast_log=str(full_trace)
158
+ )
159
+ continue
160
+
161
+ for issue in data:
162
+ try:
163
+ issue_model = CreateIacFindingInput(
164
+ asset_id=asset_id,
165
+ file_name=issue.get("file_name"),
166
+ vulnerable_line=issue.get("vulnerable_line"),
167
+ title=issue.get("title"),
168
+ description=issue.get("description"),
169
+ severity=issue.get("severity"),
170
+ code_snippet=parse_code_snippet(issue.get("code_snippet")),
171
+ reference=parse_conviso_references(issue.get("reference", "")),
172
+ first_line=issue.get("first_line"),
173
+ category=format_cwe_id(issue.get("cwe")),
174
+ original_issue_id_from_tool=issue.get('hash_issue', []),
175
+ solution=issue.get("solution"),
176
+ control_sync_status_id=control_sync_status_id
177
+ )
178
+
179
+ conviso_api.issues.create_iac(issue_model)
180
+
181
+ except ResponseError as error:
182
+ if error.code == 'RECORD_NOT_UNIQUE':
183
+ continue
184
+ else:
185
+ retry_handler = RetryHandler(
186
+ flow_context=flow_context, company_id=company_id, asset_id=asset_id
187
+ )
188
+ retry_handler.execute_with_retry(conviso_api.issues.create_iac, issue_model)
189
+ except Exception:
190
+ retry_handler = RetryHandler(
191
+ flow_context=flow_context, company_id=company_id, asset_id=asset_id
192
+ )
193
+ retry_handler.execute_with_retry(conviso_api.issues.create_iac, issue_model)
194
+
195
+ continue
196
+
197
+
198
+ def perform_command(
199
+ flow_context, asset_id, company_id, repository_dir, send_to_flow, scanner_timeout,
200
+ deploy_id, experimental, cleanup, from_ast, control_sync_status_id
201
+ ):
202
+
203
+ if send_to_flow and experimental and not asset_id:
204
+ raise click.MissingParameter(
205
+ "It is required when sending reports to Conviso Platform using experimental API.",
206
+ param_type="option",
207
+ param_hint="--asset-id",
208
+ )
209
+
210
+ try:
211
+ REQUIRED_CODEBASE_PATH = '/code'
212
+ IAC_IMAGE_NAME = 'iac_scanner_checkov'
213
+ IAC_SCAN_FILENAME = '/{}.json'.format(IAC_IMAGE_NAME)
214
+ containers_map = {
215
+ IAC_IMAGE_NAME: {
216
+ 'repository_dir': repository_dir,
217
+ 'repository_name': IAC_IMAGE_NAME,
218
+ 'tag': 'unstable',
219
+ 'command': [
220
+ '-c', REQUIRED_CODEBASE_PATH,
221
+ '-o', IAC_SCAN_FILENAME,
222
+ ],
223
+ },
224
+ }
225
+
226
+ LOGGER.info('💬 Preparing Environment...')
227
+ conviso_rest_api = flow_context.create_conviso_rest_api_client()
228
+ token = conviso_rest_api.docker_registry.get_sast_token()
229
+ scanners_wrapper = ContainerWrapper(
230
+ token=token,
231
+ containers_map=containers_map,
232
+ logger=LOGGER,
233
+ timeout=scanner_timeout
234
+ )
235
+
236
+ LOGGER.info('💬 Starting IaC...')
237
+ scanners_wrapper.run()
238
+
239
+ results_filepaths = []
240
+ for r in scanners_wrapper.scanners:
241
+ report_filepath = r.results
242
+ if report_filepath:
243
+ results_filepaths.append(report_filepath)
244
+
245
+ LOGGER.info('💬 Processing Results...')
246
+ if send_to_flow:
247
+ git_adapater = GitAdapter(repository_dir)
248
+ end_commit = git_adapater.head_commit
249
+ conviso_beta_api = flow_context.create_conviso_api_client_beta()
250
+
251
+ deploy_results_to_conviso(
252
+ conviso_beta_api, results_filepaths, asset_id, company_id, flow_context, deploy_id=deploy_id,
253
+ commit_ref=end_commit, control_sync_status_id=control_sync_status_id
254
+ )
255
+ LOGGER.info('✅ IaC Scan Finished.')
256
+
257
+ if cleanup and from_ast == False:
258
+ LOGGER.info("🧹 Cleaning up ...")
259
+ cleaner = Cleaner()
260
+ cleaner.cleanup()
261
+
262
+ except Exception as e:
263
+ on_http_error(e)
264
+ raise click.ClickException(str(e)) from e
265
+
266
+
267
+ def parse_conviso_references(references=[]):
268
+ DIVIDER = "\n"
269
+
270
+ return DIVIDER.join(references)
271
+
272
+
273
+ def parse_code_snippet(code_snippet):
274
+ lines = code_snippet.split("\n")
275
+ cleaned_lines = [line.rstrip() for line in lines if line.strip()]
276
+ code_snippet = "\n".join(cleaned_lines)
277
+
278
+ return code_snippet
279
+
280
+
281
+ def format_cwe_id(cwe_input):
282
+ cwe_str = str(cwe_input).strip()
283
+
284
+ if cwe_str.upper().startswith("CWE-"):
285
+ return cwe_str
286
+ return f"CWE-{cwe_str}"
287
+
288
+
289
+ def parse_data(sarif_result):
290
+ vulnerabilities = []
291
+
292
+ for result in sarif_result['runs'][0]['results']:
293
+
294
+ vulnerability = {
295
+ 'file_name': result['locations'][0]['physicalLocation']['artifactLocation']['uri'],
296
+ 'vulnerable_line': result['locations'][0]['physicalLocation']['region']['startLine'],
297
+ 'code_snippet': result['locations'][0]['physicalLocation']['contextRegion']['snippet']['text'],
298
+ 'title': sarif_result['runs'][0]['tool']['driver']['rules'][result['ruleIndex']]['name'],
299
+ 'description': result['message']['text'],
300
+ 'severity': result['level'],
301
+ 'first_line': result['locations'][0]['physicalLocation']['contextRegion']['startLine'],
302
+ 'cwe': result['properties']['cweId'],
303
+ 'solution': result['properties']['solution'],
304
+ 'hash_issue': result['partialFingerprints']['hashIssueV2']
305
+ }
306
+ vulnerabilities.append(vulnerability)
307
+
308
+ return vulnerabilities
309
+
310
+
311
+ EPILOG = '''
312
+ Examples:
313
+
314
+ \b
315
+ 1 - Reporting the results to Conviso Platform API:
316
+ 1.1 - Running an analysis at all commit range:
317
+ $ export CONVISO_API_KEY='your-api-key'
318
+ $ {command}
319
+
320
+ ''' # noqa: E501
321
+
322
+ SHORT_HELP = "Perform Infrastructure Code analysis"
323
+
324
+ command = 'conviso iac run'
325
+ run.short_help = SHORT_HELP
326
+ run.epilog = EPILOG.format(
327
+ command=command,
328
+ )
@@ -0,0 +1,132 @@
1
+ import re
2
+ from convisoappsec.flowcli.common import CreateDeployException
3
+ from convisoappsec.logger import LOGGER
4
+ from convisoappsec.flowcli.companies.ls import Companies
5
+ from convisoappsec.flow.graphql_api.v1.models.asset import AssetInput
6
+ from convisoappsec.common.git_data_parser import GitDataParser
7
+ from .context import pass_flow_context
8
+
9
+
10
+ class RequirementsVerifier:
11
+
12
+ @staticmethod
13
+ @pass_flow_context
14
+ def list_assets(flow_context, company_id, asset_name, scan_type):
15
+ conviso_api = flow_context.create_conviso_graphql_client()
16
+
17
+ asset_model = AssetInput(
18
+ int(company_id),
19
+ asset_name,
20
+ scan_type
21
+ )
22
+
23
+ return conviso_api.assets.list_assets(asset_model)
24
+
25
+ @staticmethod
26
+ @pass_flow_context
27
+ def create_asset(flow_context, company_id, asset_name, scan_type):
28
+ conviso_api = flow_context.create_conviso_graphql_client()
29
+
30
+ asset_model = AssetInput(
31
+ int(company_id),
32
+ asset_name,
33
+ scan_type
34
+ )
35
+
36
+ return conviso_api.assets.create_asset(asset_model)
37
+
38
+ @staticmethod
39
+ def sarif_asset_assignment(context, asset):
40
+ """ assignment asset when is a sarif import """
41
+ context.params['asset_id'] = asset['id']
42
+ context.params['experimental'] = True
43
+
44
+ return context
45
+
46
+ @staticmethod
47
+ def find_or_create_asset(context, company_id, old_name, new_name):
48
+ """ Method to find or create asset on conviso platform """
49
+ try:
50
+ existing_assets = RequirementsVerifier.list_assets(company_id, new_name, 'SAST')
51
+ if not existing_assets:
52
+ existing_assets = RequirementsVerifier.list_assets(company_id, old_name, 'SAST')
53
+ for asset in existing_assets:
54
+ if asset['name'] == old_name or asset['name'] == new_name:
55
+ LOGGER.info('✅ Asset found...')
56
+ context.params['asset_name'] = asset['name']
57
+ return [asset]
58
+ LOGGER.info('💬 Asset not found; creating...')
59
+ new_asset = RequirementsVerifier.create_asset(company_id, new_name, 'SAST')
60
+ context.params['asset_name'] = new_name
61
+ return [new_asset]
62
+ except Exception as e:
63
+ raise Exception("Error: {}".format(e))
64
+
65
+ @staticmethod
66
+ def create_asset_with_custom_name(context, company_id, asset_name):
67
+ """ Create an asset with custom name pass with a custom name """
68
+ if not asset_name or not asset_name.strip(): # Check for None or blank string
69
+ raise ValueError("Asset name cannot be None or blank.")
70
+
71
+ # we need to verify if already has an asset with the name provided.
72
+ # because graphql will return an error if already has.
73
+ existing_asset = RequirementsVerifier.list_assets(company_id, asset_name, 'SAST')
74
+
75
+ if not existing_asset:
76
+ LOGGER.info("💬 Asset not found; creating with name {}...".format(asset_name))
77
+ asset = RequirementsVerifier.create_asset(company_id, asset_name, 'SAST')
78
+ else:
79
+ LOGGER.info('✅ Asset found...')
80
+ asset = existing_asset[0]
81
+
82
+ context.params['asset_name'] = asset_name
83
+
84
+ return asset
85
+
86
+ @staticmethod
87
+ @pass_flow_context
88
+ def prepare_context(flow_context, context, from_ast=False):
89
+ """ Due to the new vulnerability management we need to do some checks before continuing the flow """
90
+
91
+ if from_ast is True:
92
+ context.params['from_ast'] = True
93
+
94
+ companies = Companies()
95
+ company_id = context.params['company_id']
96
+
97
+ if company_id is not None:
98
+ companies_filtered = [companies.ls(flow_context, company_id=company_id)]
99
+ else:
100
+ companies_filtered = companies.ls(flow_context)
101
+
102
+ if len(companies_filtered) > 1:
103
+ raise CreateDeployException(
104
+ "❌ Deploy not created. You have access to multiple companies; please specify one using CONVISO_COMPANY_ID."
105
+ )
106
+
107
+ company = companies_filtered[0]
108
+ company_id = company['id']
109
+
110
+ if context.params['asset_name'] is not None:
111
+ # if user use --asset-name param or envvar CONVISO_ASSET_NAME, FLOW_ASSET_NAME
112
+ asset_name = context.params['asset_name']
113
+ asset = RequirementsVerifier.create_asset_with_custom_name(context, company_id, asset_name)
114
+ else:
115
+ pattern = r"\([^)]*\)" # eliminating what is in parentheses
116
+ old_asset_name = GitDataParser(context.params['repository_dir']).parse_name()
117
+ new_asset_name = re.sub(pattern, '', old_asset_name).strip()
118
+
119
+ assets = RequirementsVerifier.find_or_create_asset(context, company_id, old_asset_name, new_asset_name)
120
+ asset = assets[0]
121
+
122
+ if 'input_file' in context.params:
123
+ # sarif only uses assets, not requiring the creation of a project.
124
+ RequirementsVerifier.sarif_asset_assignment(context, asset)
125
+
126
+ return context
127
+
128
+ context.params['asset_id'] = asset['id']
129
+ context.params['experimental'] = True
130
+ context.params['company_id'] = company_id
131
+
132
+ return context
@@ -0,0 +1,3 @@
1
+ from .entrypoint import sast
2
+
3
+ __all__ = ['sast']
@@ -0,0 +1,17 @@
1
+ import click
2
+
3
+ from convisoappsec.flowcli import help_option
4
+ from .run import run
5
+
6
+
7
+ @click.group()
8
+ @help_option
9
+ def sast():
10
+ pass
11
+
12
+
13
+ sast.add_command(run)
14
+
15
+ sast.epilog = '''
16
+ Run flow sast COMMAND --help for more information on a command.
17
+ '''