regscale-cli 6.23.0.0__py3-none-any.whl → 6.24.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.
Potentially problematic release.
This version of regscale-cli might be problematic. Click here for more details.
- regscale/_version.py +1 -1
- regscale/core/app/application.py +2 -0
- regscale/integrations/commercial/__init__.py +1 -0
- regscale/integrations/commercial/sarif/sarif_converter.py +1 -1
- regscale/integrations/commercial/wizv2/click.py +109 -2
- regscale/integrations/commercial/wizv2/compliance_report.py +1485 -0
- regscale/integrations/commercial/wizv2/constants.py +72 -2
- regscale/integrations/commercial/wizv2/data_fetcher.py +61 -0
- regscale/integrations/commercial/wizv2/file_cleanup.py +104 -0
- regscale/integrations/commercial/wizv2/issue.py +775 -27
- regscale/integrations/commercial/wizv2/policy_compliance.py +599 -181
- regscale/integrations/commercial/wizv2/reports.py +243 -0
- regscale/integrations/commercial/wizv2/scanner.py +668 -245
- regscale/integrations/compliance_integration.py +304 -51
- regscale/integrations/due_date_handler.py +210 -0
- regscale/integrations/public/cci_importer.py +444 -0
- regscale/integrations/scanner_integration.py +718 -153
- regscale/models/integration_models/CCI_List.xml +1 -0
- regscale/models/integration_models/cisa_kev_data.json +61 -3
- regscale/models/integration_models/synqly_models/capabilities.json +1 -1
- regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +3 -3
- regscale/models/regscale_models/form_field_value.py +1 -1
- regscale/models/regscale_models/milestone.py +1 -0
- regscale/models/regscale_models/regscale_model.py +225 -60
- regscale/models/regscale_models/security_plan.py +3 -2
- regscale/regscale.py +7 -0
- {regscale_cli-6.23.0.0.dist-info → regscale_cli-6.24.0.0.dist-info}/METADATA +9 -9
- {regscale_cli-6.23.0.0.dist-info → regscale_cli-6.24.0.0.dist-info}/RECORD +44 -27
- tests/fixtures/test_fixture.py +13 -8
- tests/regscale/integrations/public/__init__.py +0 -0
- tests/regscale/integrations/public/test_alienvault.py +220 -0
- tests/regscale/integrations/public/test_cci.py +458 -0
- tests/regscale/integrations/public/test_cisa.py +1021 -0
- tests/regscale/integrations/public/test_emass.py +518 -0
- tests/regscale/integrations/public/test_fedramp.py +851 -0
- tests/regscale/integrations/public/test_fedramp_cis_crm.py +3661 -0
- tests/regscale/integrations/public/test_file_uploads.py +506 -0
- tests/regscale/integrations/public/test_oscal.py +453 -0
- tests/regscale/models/test_form_field_value_integration.py +304 -0
- tests/regscale/models/test_module_integration.py +582 -0
- {regscale_cli-6.23.0.0.dist-info → regscale_cli-6.24.0.0.dist-info}/LICENSE +0 -0
- {regscale_cli-6.23.0.0.dist-info → regscale_cli-6.24.0.0.dist-info}/WHEEL +0 -0
- {regscale_cli-6.23.0.0.dist-info → regscale_cli-6.24.0.0.dist-info}/entry_points.txt +0 -0
- {regscale_cli-6.23.0.0.dist-info → regscale_cli-6.24.0.0.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
regscale/__init__.py,sha256=ZygAIkX6Nbjag1czWdQa-yP-GM1mBE_9ss21Xh__JFc,34
|
|
2
|
-
regscale/_version.py,sha256=
|
|
3
|
-
regscale/regscale.py,sha256=
|
|
2
|
+
regscale/_version.py,sha256=aEKcQkG8x8HCLF1r9TPYAUjkbrx8MzUY1sWdBWNufv4,1198
|
|
3
|
+
regscale/regscale.py,sha256=u25AiF58XIfAG2fKjqxVWDhaAOK8-gZ19Y-eWYlM5TI,31480
|
|
4
4
|
regscale/airflow/__init__.py,sha256=yMwN0Bz4JbM0nl5qY_hPegxo_O2ilhTOL9PY5Njhn-s,270
|
|
5
5
|
regscale/airflow/click_dags.py,sha256=H3SUR5jkvInNMv1gu-VG-Ja_H-kH145CpQYNalWNAbE,4520
|
|
6
6
|
regscale/airflow/click_mixins.py,sha256=BTwKWsEu6KVtlrzFbXpD_RuEpMzc-CSnCCySUzqzCgQ,3571
|
|
@@ -36,7 +36,7 @@ regscale/core/lazy_group.py,sha256=S2-nA5tzm47A929NOTqGkzrzKuZQDlq2OAPbNnG1W1Q,2
|
|
|
36
36
|
regscale/core/login.py,sha256=-8vy1HVAtv1iARnZh6uzYtwmx8VFYPwLYR0QAf1ttCk,2714
|
|
37
37
|
regscale/core/app/__init__.py,sha256=nGcCN1vWBAnZzoccIlt0jwWQdegCOrBWOB7LPhQkQSs,96
|
|
38
38
|
regscale/core/app/api.py,sha256=vDcdvXLz9hEu6R-U-f9z7zZ-aXmmhCjiUKlhzm5M6zA,23602
|
|
39
|
-
regscale/core/app/application.py,sha256=
|
|
39
|
+
regscale/core/app/application.py,sha256=dRiG8X7LFfs5KuLOgZlJWZ_WVs9EitNxNuRYZCi25-c,32104
|
|
40
40
|
regscale/core/app/logz.py,sha256=8AdBKmquv45JGi5fCMc38JqQg6-FpUONGmqfd5EGwrI,2583
|
|
41
41
|
regscale/core/app/internal/__init__.py,sha256=rod4nmE7rrYDdbuYF4mCWz49TK_2r-v4tWy1UHW63r0,4808
|
|
42
42
|
regscale/core/app/internal/admin_actions.py,sha256=hOdma7QGwFblmxEj9UTjiWWmZGUS5_ZFtxL2qZdhf-Q,7443
|
|
@@ -111,12 +111,13 @@ regscale/exceptions/validation_exception.py,sha256=_DW_GARtPr_Dyy8tolnvC_AYsHRsU
|
|
|
111
111
|
regscale/integrations/__init__.py,sha256=Sqthp3Jggo7co_go380cLn3OAb0cHwqL609_4QJSFBY,58
|
|
112
112
|
regscale/integrations/api_paginator.py,sha256=73rjaNM9mGv8evHAeoObXEjZPg-bJuGPo60ewCLEil8,33192
|
|
113
113
|
regscale/integrations/api_paginator_example.py,sha256=lEuYI-xEGcjnXuIzbCobCP0YRuukLF0s8S3d382SAH4,12119
|
|
114
|
-
regscale/integrations/compliance_integration.py,sha256=
|
|
114
|
+
regscale/integrations/compliance_integration.py,sha256=cyc8iPGhKgvb7G9sN1ja4Fi4Rq91llBnJbTkGSKHINE,79967
|
|
115
|
+
regscale/integrations/due_date_handler.py,sha256=qIOeFx4LPvOTpqJx8JV5Hj3FLlx0FoaYAsFoXqxYBcs,8343
|
|
115
116
|
regscale/integrations/integration_override.py,sha256=HjYBCuvNpU3t3FptaqYAkdexLFOZBAFrFE9xU0RD1Nc,5867
|
|
116
117
|
regscale/integrations/jsonl_scanner_integration.py,sha256=l8nq_T3rE1XX-6HxrNHm3xzxCNWbIjxQvGMdtZWs7KQ,57003
|
|
117
|
-
regscale/integrations/scanner_integration.py,sha256=
|
|
118
|
+
regscale/integrations/scanner_integration.py,sha256=Xglq93nS-B4D4eyGXlU47CcAvp-wckK0AjmSWoPtjeQ,186305
|
|
118
119
|
regscale/integrations/variables.py,sha256=MfQ34WuYVN5437A9sZ2ssHRkA3gFhMHfk1DVasceGmY,2336
|
|
119
|
-
regscale/integrations/commercial/__init__.py,sha256=
|
|
120
|
+
regscale/integrations/commercial/__init__.py,sha256=fFiuXp-uOFd5HWLKa0PeKw3425OvZqPvsMe8bvh8n_s,14371
|
|
120
121
|
regscale/integrations/commercial/ad.py,sha256=YXSmK8vRf6yi2GnREGa5GrE6GelhFrLj44SY8AO1pK0,15509
|
|
121
122
|
regscale/integrations/commercial/burp.py,sha256=3BLNKLfwL1x7jfhd8MJD6hdHEpj58pOEtrtCkn2hcWA,3344
|
|
122
123
|
regscale/integrations/commercial/cpe.py,sha256=vUHKGdq0UlR38pZWqqHLLTdDfooLtE9zIiFHdoFcUr0,5735
|
|
@@ -203,7 +204,7 @@ regscale/integrations/commercial/sap/tenable/click.py,sha256=vCdRe6d5ey6mywtL8GY
|
|
|
203
204
|
regscale/integrations/commercial/sap/tenable/scanner.py,sha256=eeXXe2b-zoth80pVcasO7Cy-3NhW_4PcDhin1G8hj0o,9363
|
|
204
205
|
regscale/integrations/commercial/sarif/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
205
206
|
regscale/integrations/commercial/sarif/sairf_importer.py,sha256=gCuDsybT0jbhCtQLJW0L88hLxUpWIgatVERU4D6_9Xc,17886
|
|
206
|
-
regscale/integrations/commercial/sarif/sarif_converter.py,sha256=
|
|
207
|
+
regscale/integrations/commercial/sarif/sarif_converter.py,sha256=3KJ7GBt8iJzTKdlUNq5rRx9JaoIHcESdbQim7AfhvNk,1910
|
|
207
208
|
regscale/integrations/commercial/sicura/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
208
209
|
regscale/integrations/commercial/sicura/api.py,sha256=4FDM3ATk8bysdGaBtcfsexlZoTHUf-ckA60eGrK-KDk,32151
|
|
209
210
|
regscale/integrations/commercial/sicura/commands.py,sha256=-54gqCpmGECC1ph5Wpr8cwYhBscsQy1V_24-xQ0sFyw,1874
|
|
@@ -237,16 +238,19 @@ regscale/integrations/commercial/trivy/scanner.py,sha256=iiwTvjqRlLRgQvCs_FP0j83
|
|
|
237
238
|
regscale/integrations/commercial/wizv2/WizDataMixin.py,sha256=s7F_rVrP9IZa_x_vh3MswR7W_UBHRfd4kHGVsNX4ips,3606
|
|
238
239
|
regscale/integrations/commercial/wizv2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
239
240
|
regscale/integrations/commercial/wizv2/async_client.py,sha256=CElkHxbSlNfRnvJpf4JTBD293NJxQsR-QaTBuHINrLw,12946
|
|
240
|
-
regscale/integrations/commercial/wizv2/click.py,sha256=
|
|
241
|
-
regscale/integrations/commercial/wizv2/
|
|
242
|
-
regscale/integrations/commercial/wizv2/
|
|
241
|
+
regscale/integrations/commercial/wizv2/click.py,sha256=N5GLs3q-oMJzJqqEfy9luuXjc7yKSb0ibLRYmYGqZqw,18873
|
|
242
|
+
regscale/integrations/commercial/wizv2/compliance_report.py,sha256=_Ntrq_uaGU6JW5keCxZKKBsA17FZwvHlQ9afS5euwog,62959
|
|
243
|
+
regscale/integrations/commercial/wizv2/constants.py,sha256=emJHsfdsRuHhWTYqADV4-l6sZNJ-nWGj_l1abdFrXxk,49308
|
|
244
|
+
regscale/integrations/commercial/wizv2/data_fetcher.py,sha256=CmJyUCeTQIkYBu2LPicpTNwXJrYkRP3xxM55BJQhr2A,16258
|
|
245
|
+
regscale/integrations/commercial/wizv2/file_cleanup.py,sha256=ENBO9RDXL2kyHkBYaSai83i4kVTUJUF_F0JCj84i-ow,4178
|
|
243
246
|
regscale/integrations/commercial/wizv2/finding_processor.py,sha256=Rn2dYob4cz24_Ks-UTwNQe-KQ6hmFWS6GB8PQXV0ZPE,11361
|
|
244
|
-
regscale/integrations/commercial/wizv2/issue.py,sha256=
|
|
247
|
+
regscale/integrations/commercial/wizv2/issue.py,sha256=CHTuQoeXPmnTh13hUBI2RDbShlrRT9xn58ul5_MUan8,46233
|
|
245
248
|
regscale/integrations/commercial/wizv2/parsers.py,sha256=dsSMiZaUrBXbuW7U-I5nLoF-TQlpvXys83sTSqT4Yks,11819
|
|
246
|
-
regscale/integrations/commercial/wizv2/policy_compliance.py,sha256=
|
|
249
|
+
regscale/integrations/commercial/wizv2/policy_compliance.py,sha256=YU5TFd2RfESAnfzkog091G30CDlMobt6zOd1NXV2SP4,151984
|
|
247
250
|
regscale/integrations/commercial/wizv2/policy_compliance_helpers.py,sha256=-KAlDxMiojyUX2DtUi3uVbpmFhDLtGs7wj11MPBCaRE,22174
|
|
251
|
+
regscale/integrations/commercial/wizv2/reports.py,sha256=CFfSDaS6glJhKA66lDTfenl632YQiGYb_z0CeMbl4Kk,8789
|
|
248
252
|
regscale/integrations/commercial/wizv2/sbom.py,sha256=QcGaYiBGtZ3mBcbo-KGl-I2u6QHKAIinTk26LPy0Kng,4466
|
|
249
|
-
regscale/integrations/commercial/wizv2/scanner.py,sha256=
|
|
253
|
+
regscale/integrations/commercial/wizv2/scanner.py,sha256=EdvnEp7Tb7YK9LMkZ2KhzotQY87J1RBbI0orUzG1GY0,96144
|
|
250
254
|
regscale/integrations/commercial/wizv2/utils.py,sha256=npdIwR_XG_5VZkr_YXgMe8cjhcYKncNndglD55qwWc8,55996
|
|
251
255
|
regscale/integrations/commercial/wizv2/variables.py,sha256=2DVIN4JPYX9hN6wTdEI9ZdHXYDPpYSu4mAC0yVibPLg,1992
|
|
252
256
|
regscale/integrations/commercial/wizv2/wiz_auth.py,sha256=qGcUhpC9eRkJIngmv3i9yHdp0q9rv6AvA5gHkypYzCE,5549
|
|
@@ -255,6 +259,7 @@ regscale/integrations/integration/integration.py,sha256=pr_fbqBieYbqp3PdBjuqKuZC
|
|
|
255
259
|
regscale/integrations/integration/inventory.py,sha256=gHL1a6VSV3zf4DTmksEy8qXNrqhIun8TwLxhRpuEMqY,341
|
|
256
260
|
regscale/integrations/integration/issue.py,sha256=HaCF_5F_U_E5ecYlMgOZiM-yhXnt7OLj47OAJkf9X3g,3507
|
|
257
261
|
regscale/integrations/public/__init__.py,sha256=D4RyJhTGFRkrh_cJUfIbWCldue-DDcunuFuprBzKxFY,3261
|
|
262
|
+
regscale/integrations/public/cci_importer.py,sha256=gvvBDqtPYpP7K7nB5da4bxg5PtIyKHKNVxdbGps9QUU,16155
|
|
258
263
|
regscale/integrations/public/cisa.py,sha256=EE2rN4GWWEk5VLt4iMVwGMYB6yYPxe6KyW_tLs8dDmA,21870
|
|
259
264
|
regscale/integrations/public/criticality_updater.py,sha256=bekadBBJkym5Dd9JZFNQmY3I0e1xgBvxkyVwgCNOKus,2806
|
|
260
265
|
regscale/integrations/public/emass.py,sha256=culHHuXUlVYkB6DcVcnUvpBzU1eRyyVGgsJ3KqC8HOw,13672
|
|
@@ -316,13 +321,14 @@ regscale/models/app_models/datetime_encoder.py,sha256=AvKkXWhrd87jTfNnY5Q2gw5IdX
|
|
|
316
321
|
regscale/models/app_models/import_validater.py,sha256=p9ZFqryVxDT1w8RJ5EOKuBQbNFVl2AcuY-LOr4ZNsMM,13932
|
|
317
322
|
regscale/models/app_models/mapping.py,sha256=tga2kCsEZT-YvnJIgiHy_qRcFp25Xzk0YkbkkZgwSEA,11265
|
|
318
323
|
regscale/models/app_models/pipeline.py,sha256=qzrkQvvW6d8rqbBjMR8wkT2obez0tnKyY_TxtxLh6VE,909
|
|
324
|
+
regscale/models/integration_models/CCI_List.xml,sha256=qwHzCrZ3KQnLLmrF6J9dE_trhVcUdIw-7WFTtvPmNLM,3226054
|
|
319
325
|
regscale/models/integration_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
320
326
|
regscale/models/integration_models/aqua.py,sha256=XR2qrzCOI_bXrFPVcgbxUyaE1m0Oe2NSH7ph1hn8q2w,10697
|
|
321
327
|
regscale/models/integration_models/azure_alerts.py,sha256=2etrpvcxa7jVQrc98bJlVGd3xPcw-YwJ65c3pfSf0uA,8408
|
|
322
328
|
regscale/models/integration_models/base64.py,sha256=sxV6O5qY1_TstJENX5jBPsSdQwmA83-NNhgJFunXiZE,570
|
|
323
329
|
regscale/models/integration_models/burp.py,sha256=FBEBkH3U0Q8vq71FFoWnvgLRF5Hkr9GYmQFmNNHFrVk,16932
|
|
324
330
|
regscale/models/integration_models/burp_models.py,sha256=UytDTAcCaxyu-knFkm_mEUH6UmWK3OTXKSC9Sc6OjVs,3669
|
|
325
|
-
regscale/models/integration_models/cisa_kev_data.json,sha256=
|
|
331
|
+
regscale/models/integration_models/cisa_kev_data.json,sha256=ThBF9xf2lRbdlWY1ucsdJU7u6ysXCBqMG80S9MMds2s,1268609
|
|
326
332
|
regscale/models/integration_models/defender_data.py,sha256=jsAcjKxiGmumGerj7xSWkFd6r__YpuKDnYX5o7xHDiE,2844
|
|
327
333
|
regscale/models/integration_models/defenderimport.py,sha256=Ze4kgwns-IYPyO7sBjEzW8PXWlxwU-DAo2fIyRcTC3k,6242
|
|
328
334
|
regscale/models/integration_models/drf.py,sha256=Aq7AdLa_CH97NrnR-CxaFI22JjVN9uCxVN7Z-BBUaNU,18896
|
|
@@ -353,7 +359,7 @@ regscale/models/integration_models/flat_file_importer/__init__.py,sha256=HYO7mrq
|
|
|
353
359
|
regscale/models/integration_models/sbom/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
354
360
|
regscale/models/integration_models/sbom/cyclone_dx.py,sha256=0pFR0BWBrF5c8_cC_8mj2MXvNOMHOdHbBYXvTVfFAh8,4058
|
|
355
361
|
regscale/models/integration_models/synqly_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
356
|
-
regscale/models/integration_models/synqly_models/capabilities.json,sha256=
|
|
362
|
+
regscale/models/integration_models/synqly_models/capabilities.json,sha256=R7Oq3YrgFc3HVS0X8DvXrAsAnLIgmos8Rih2PVxh6R4,399849
|
|
357
363
|
regscale/models/integration_models/synqly_models/connector_types.py,sha256=8nxptkTexpskySnmL0obNAff_iu_fx6tJ7i1-4hJvao,461
|
|
358
364
|
regscale/models/integration_models/synqly_models/ocsf_mapper.py,sha256=ftObPhGg9CamnwRZ5z6qi8pW2Gu4JYy8apEo33o7q00,16960
|
|
359
365
|
regscale/models/integration_models/synqly_models/param.py,sha256=Xt5Zm6lC_VkLj7LF2qXo72TJZHysqttsp5ai0NCf1po,2643
|
|
@@ -363,7 +369,7 @@ regscale/models/integration_models/synqly_models/connectors/__init__.py,sha256=J
|
|
|
363
369
|
regscale/models/integration_models/synqly_models/connectors/assets.py,sha256=HHNIAVh5pRuJe8sStqhFEc6VnX2wT0FcY5178nbQgkQ,3705
|
|
364
370
|
regscale/models/integration_models/synqly_models/connectors/edr.py,sha256=kio3uoEYubCHretpDOJqxdwmzid1IzbVYz0BF64zeL0,5547
|
|
365
371
|
regscale/models/integration_models/synqly_models/connectors/ticketing.py,sha256=yRBuCkRAVfa_C91r3WqJ9gxrQsoD0qV9cY48YXpJl70,25358
|
|
366
|
-
regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py,sha256=
|
|
372
|
+
regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py,sha256=jebBkFy6KspZMVGkmLWQm8-enAUsjRJ6z3pM6Wg0Qv0,7193
|
|
367
373
|
regscale/models/integration_models/tenable_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
368
374
|
regscale/models/integration_models/tenable_models/integration.py,sha256=lplL8zmjTFuhLreW-4y7G1fiCOBgzNAaATq800jgTQc,10271
|
|
369
375
|
regscale/models/integration_models/tenable_models/models.py,sha256=dmG7btkN4YkDWwnfW5Ldc3tWEAGjPiaRgJjrqMOkPEU,15846
|
|
@@ -402,7 +408,7 @@ regscale/models/regscale_models/evidence_mapping.py,sha256=eovTJsl1cjZMvbhpOv70n
|
|
|
402
408
|
regscale/models/regscale_models/facility.py,sha256=J3gGv0Tf3zNdyKGhb0iM8WjgjWqJHZLKdcN9n-jDrTA,1059
|
|
403
409
|
regscale/models/regscale_models/file.py,sha256=zHIZvhgxMWTXX5ku98dRJcDSQ1VrRyUuorA6N9YEBzU,14711
|
|
404
410
|
regscale/models/regscale_models/filetag.py,sha256=jd99xcQsGheLFfy7PYtZEzT-re_Dp_ZoUF3GWYMsi0Q,1138
|
|
405
|
-
regscale/models/regscale_models/form_field_value.py,sha256=
|
|
411
|
+
regscale/models/regscale_models/form_field_value.py,sha256=Xd6pqt51YFi8snhC-rqeUqSK7xjKbICQ1ZPvPaQdJLg,5869
|
|
406
412
|
regscale/models/regscale_models/functional_roles.py,sha256=Vm_j-UZBKoaiONO75VqqCKnDHE6ynP0X5XZmKXl8UT8,932
|
|
407
413
|
regscale/models/regscale_models/group.py,sha256=HpAkW6RmuCepSqhVbiySeaWvbMi7SzQr81hkXWhsVI4,6269
|
|
408
414
|
regscale/models/regscale_models/implementation_objective.py,sha256=e0Hamt-9RBeHRDzlWDbIJ3t4qnZKXPrbsesBK3wYoNk,12132
|
|
@@ -418,7 +424,7 @@ regscale/models/regscale_models/line_of_inquiry.py,sha256=Uu0lQEhif0W6yTSkJo27Gy
|
|
|
418
424
|
regscale/models/regscale_models/link.py,sha256=lAY4Ig3Menm1EqfcAbVJ7jsCsRO5tWtJIf-9-G9FXT8,6593
|
|
419
425
|
regscale/models/regscale_models/master_assessment.py,sha256=t03-8vQJ7hnPNgEU0GSC1XGKOgAqHKuIupbt5IjJvtI,7322
|
|
420
426
|
regscale/models/regscale_models/meta_data.py,sha256=Fg8rrWSTx3K00QkF4glH9UdY9OFWJ4_UqxleLSSbx8I,2482
|
|
421
|
-
regscale/models/regscale_models/milestone.py,sha256=
|
|
427
|
+
regscale/models/regscale_models/milestone.py,sha256=gSgOJBxJlF_wu40sknvgwF94u-a9Nt7wtBrG7UzP_48,1977
|
|
422
428
|
regscale/models/regscale_models/module.py,sha256=a7lalHmVTQ04ZILnJxuFWdHYDtyusBMTtonD4ICL-Wc,7272
|
|
423
429
|
regscale/models/regscale_models/modules.py,sha256=yeva_tct88o2NFt93_zmqUcXZ3LucVbAv5FvQPru3cQ,8551
|
|
424
430
|
regscale/models/regscale_models/objective.py,sha256=aJIpmkZ-NscqV2y8SGB4HYzm615b6mklyHnW9bL2ljk,249
|
|
@@ -437,7 +443,7 @@ regscale/models/regscale_models/questionnaire.py,sha256=QMSXfNpSoaS8tkeo80C7OWLj
|
|
|
437
443
|
regscale/models/regscale_models/questionnaire_instance.py,sha256=1LgGTwFACmWx2xOOqUKhAUOms4_3L6NZySzuteg0_sI,8241
|
|
438
444
|
regscale/models/regscale_models/rbac.py,sha256=ulT9BzOpYNNVlBVfOmreGDTTAgzkAY5Si2rQhhIcUmY,5302
|
|
439
445
|
regscale/models/regscale_models/reference.py,sha256=P_7jT6H-NZIa7TyH3j98N-ZHlB6FsjpZVRZCCpms-D4,3253
|
|
440
|
-
regscale/models/regscale_models/regscale_model.py,sha256=
|
|
446
|
+
regscale/models/regscale_models/regscale_model.py,sha256=uhl1ZDABXcpem1ark3X-PFi1Mt_-JQ2-6g6mWSzTua4,76280
|
|
441
447
|
regscale/models/regscale_models/requirement.py,sha256=-8PnMbuWAZHol5X1w-fzm-moD784Et0oevSVbz6xLhU,767
|
|
442
448
|
regscale/models/regscale_models/risk.py,sha256=lZFDYPpTt0aEYCrYz5FBKk1Y4y2CKXYU1A8eEKT3zzg,8661
|
|
443
449
|
regscale/models/regscale_models/risk_issue_mapping.py,sha256=j6uR0x6xymJ0BsIwgnadeUQDshHNhU3VnpyItZp4dc4,2393
|
|
@@ -446,7 +452,7 @@ regscale/models/regscale_models/sbom.py,sha256=UYS3lBizGqz7A7vNPYBYzpL8PWIaXLl7Z
|
|
|
446
452
|
regscale/models/regscale_models/scan_history.py,sha256=o4e9P2rQlqlLj4mbgSPX44jutTJo1nocI1DDXyWyf6w,16741
|
|
447
453
|
regscale/models/regscale_models/search.py,sha256=rPbFDCnnBRHY5JJv9Ev3_6GjMlkdhUAsaUzC97eE2Ys,1015
|
|
448
454
|
regscale/models/regscale_models/security_control.py,sha256=GJEMkIh6IDX7Gs_z7ppmm0hqiXjC5qSbSYRYt85wOUg,6365
|
|
449
|
-
regscale/models/regscale_models/security_plan.py,sha256=
|
|
455
|
+
regscale/models/regscale_models/security_plan.py,sha256=Gccun2-rBf4SgOHGE1AJCNXFCEf_XO7oOvMJWB5qe3w,8676
|
|
450
456
|
regscale/models/regscale_models/software_inventory.py,sha256=FRAIfoUlS0kaX1HQRDyV5q4yxwRHilXbS52NSj6exo0,5555
|
|
451
457
|
regscale/models/regscale_models/stake_holder.py,sha256=JIuDTIky_3acDl-NOMwylTHkppN38JgPDZ1A6wM-BGE,1956
|
|
452
458
|
regscale/models/regscale_models/stig.py,sha256=y-PQuGg3pwDTfsNZGW6anaNAjIZBQoNe7GOLMiT5zfw,26329
|
|
@@ -498,7 +504,7 @@ regscale/visualization/click.py,sha256=-fxIwc-RrI3iHdMNTk_dhplC8yUjZXcWuHfZa7ULR
|
|
|
498
504
|
tests/fixtures/__init__.py,sha256=sLuJtRNqBRm8lpE2yKvZFIqwtYho5A5O8KbJj_IpKhQ,41
|
|
499
505
|
tests/fixtures/api.py,sha256=32EY2VZxumbPAP58ZkS0_SH4UewY9Z-ZzWrP2Unwnog,2629
|
|
500
506
|
tests/fixtures/models.py,sha256=pWKwexocbJDfMGdiuafgHEz1RklO_24znfd3LsgdXEs,3569
|
|
501
|
-
tests/fixtures/test_fixture.py,sha256=
|
|
507
|
+
tests/fixtures/test_fixture.py,sha256=zJOcgOp7kpJqX69hwaV7CtBnWg3oAHY8qIp3XsB2EnM,8491
|
|
502
508
|
tests/mocks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
503
509
|
tests/mocks/objects.py,sha256=KfCpzXpwWl-3zCLihQ3ZrQONW8Jk7F4UbcAgPz2LnnQ,99
|
|
504
510
|
tests/mocks/response.py,sha256=fUF2jrrxgmGUKXUcWWOSA457yrEyM1EB28G6RqPO9a0,1040
|
|
@@ -522,23 +528,34 @@ tests/regscale/integrations/test_issue_due_date.py,sha256=Dh2JAxgOdbucIOGtxfefsY
|
|
|
522
528
|
tests/regscale/integrations/test_property_and_milestone_creation.py,sha256=2Rx2maM7-4DMYpOH4pV6vcx3NDA84wXfqMwGvaAMVBo,26555
|
|
523
529
|
tests/regscale/integrations/test_update_finding_dates.py,sha256=2cyDpwnZUS965f84hNE4rb8BjuAYOLMK-zuLD6nai9k,13517
|
|
524
530
|
tests/regscale/integrations/test_wiz_policy_compliance_affected_controls.py,sha256=nFqOjr4-JRjZ0fJTQEhwsvnl56g4GRdX0yvS1wRpqUY,5845
|
|
531
|
+
tests/regscale/integrations/public/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
532
|
+
tests/regscale/integrations/public/test_alienvault.py,sha256=epxuflNgibIl1aYCU0FTVXXFWJbiqt0mYBV4HVaZYuw,9211
|
|
533
|
+
tests/regscale/integrations/public/test_cci.py,sha256=Zv5igmyYJpAwIAHrGQ-3Pd8MLvY8bh-B5FALL41PPU8,19525
|
|
534
|
+
tests/regscale/integrations/public/test_cisa.py,sha256=onfmI-8Nuhr7g0C87gweGoWhAubcqkmammRUD8QCQFE,41376
|
|
535
|
+
tests/regscale/integrations/public/test_emass.py,sha256=fDjQcsiXFhWGB399fikfW_khCrixB3nEL3cBlAm4XbQ,21797
|
|
536
|
+
tests/regscale/integrations/public/test_fedramp.py,sha256=MSJLtlZXXwz5FixL1LwvavHeRe8BAW1mU5zWaG0N9tY,57022
|
|
537
|
+
tests/regscale/integrations/public/test_fedramp_cis_crm.py,sha256=i97r1ZdJHOdpQYPD-C2e8sFKllb8nhDgFm8gJVS-Kks,148169
|
|
538
|
+
tests/regscale/integrations/public/test_file_uploads.py,sha256=9hAxz8fM-pZzJye_E619gJCqXNTP1pKr8ML270QE3gU,21001
|
|
539
|
+
tests/regscale/integrations/public/test_oscal.py,sha256=XVAM2WicWH6trvk4jcCKVuMiJUFjsoAJmf2J-Q3aeY8,16900
|
|
525
540
|
tests/regscale/integrations/transformer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
526
541
|
tests/regscale/integrations/transformer/test_data_transformer.py,sha256=Na-trXL2n97b6H6V9CwVU4nvqkL8HMy7E2yvAuhKtSo,36584
|
|
527
542
|
tests/regscale/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
528
543
|
tests/regscale/models/test_asset.py,sha256=YVQ0wAyjOf6LyhbUnNCHgI5-7VMKlBvb7dU886r7br8,16668
|
|
529
544
|
tests/regscale/models/test_config.py,sha256=r2mIJJDpmnLYZjw8Nw7yTzwZCsHbmfZD4rHSupfeOec,797
|
|
530
545
|
tests/regscale/models/test_control_implementation.py,sha256=r3J5B5TnsVJfnKnQq6KlYiJnt7F1kwRr5FzZh58YcFE,1060
|
|
546
|
+
tests/regscale/models/test_form_field_value_integration.py,sha256=HDYrJvEbvl9B_ql72onVbbeQEoCJdcinIx0FuGQvFn4,12391
|
|
531
547
|
tests/regscale/models/test_import.py,sha256=wG6KThJOXJe4wlFZpv4J0Lnpe4IBmU7VE13Sl4FT7xw,3949
|
|
532
548
|
tests/regscale/models/test_issue.py,sha256=7yEMAA7h08pvgoRWJtlzRaQN4JPB6CwU4zCThm5LunI,1038
|
|
533
549
|
tests/regscale/models/test_mapping.py,sha256=LE3cHETIeQ61lfYzIN2M9zlnECVb0alVe3DSCDvfwFU,1269
|
|
550
|
+
tests/regscale/models/test_module_integration.py,sha256=cCYO7wf5qvmUH33_QgtGJg-06eKAc3IYFqrsKD5RSUs,22037
|
|
534
551
|
tests/regscale/models/test_platform.py,sha256=9KW9frA7S_hNc8thC5D4sK63DTzFLZ3XE47wvcDxW-M,978
|
|
535
552
|
tests/regscale/models/test_regscale_model.py,sha256=ZsrEZkC4EtdIsoQuayn1xv2gEGcVzzozDITKJd7vYIc,12182
|
|
536
553
|
tests/regscale/models/test_report.py,sha256=IqUq7C__a1_q_mLaz0PE9Lq6fHggBsB14-AzEYNBxLw,4666
|
|
537
554
|
tests/regscale/models/test_tenable_integrations.py,sha256=y1qaW77H094VSGHjZdlvF66UCt-nPEib9Mv3cdwbM94,32435
|
|
538
555
|
tests/regscale/models/test_user_model.py,sha256=e9olv28qBApgnvK6hFHOgXjUC-pkaV8aGDirEIWASL4,4427
|
|
539
|
-
regscale_cli-6.
|
|
540
|
-
regscale_cli-6.
|
|
541
|
-
regscale_cli-6.
|
|
542
|
-
regscale_cli-6.
|
|
543
|
-
regscale_cli-6.
|
|
544
|
-
regscale_cli-6.
|
|
556
|
+
regscale_cli-6.24.0.0.dist-info/LICENSE,sha256=ytNhYQ9Rmhj_m-EX2pPq9Ld6tH5wrqqDYg-fCf46WDU,1076
|
|
557
|
+
regscale_cli-6.24.0.0.dist-info/METADATA,sha256=6T2bohVMlgbNakpTUiGWynlNicpTrapmkXGtBXxS7zQ,35027
|
|
558
|
+
regscale_cli-6.24.0.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
559
|
+
regscale_cli-6.24.0.0.dist-info/entry_points.txt,sha256=cLOaIP1eRv1yZ2u7BvpE3aB4x3kDrDwkpeisKOu33z8,269
|
|
560
|
+
regscale_cli-6.24.0.0.dist-info/top_level.txt,sha256=Uv8VUCAdxRm70bgrD4YNEJUmDhBThad_1aaEFGwRByc,15
|
|
561
|
+
regscale_cli-6.24.0.0.dist-info/RECORD,,
|
tests/fixtures/test_fixture.py
CHANGED
|
@@ -141,14 +141,19 @@ class CLITestFixture:
|
|
|
141
141
|
self.config = self.app.config
|
|
142
142
|
self.title_prefix = generate_uuid
|
|
143
143
|
# login with token if available
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
144
|
+
try:
|
|
145
|
+
if token := os.getenv("REGSCALE_TOKEN") or self.config.get("token"):
|
|
146
|
+
login(token=token, app=self.app)
|
|
147
|
+
elif "REGSCALE_USERNAME" in os.environ and "REGSCALE_PASSWORD" in os.environ:
|
|
148
|
+
login(
|
|
149
|
+
str_user=os.getenv("REGSCALE_USERNAME"),
|
|
150
|
+
str_password=os.getenv("REGSCALE_PASSWORD"),
|
|
151
|
+
app=self.app,
|
|
152
|
+
)
|
|
153
|
+
except SystemExit:
|
|
154
|
+
# In test environment, don't exit on authentication failure
|
|
155
|
+
logger.warning("Authentication failed in test environment - continuing without authentication")
|
|
156
|
+
pass
|
|
152
157
|
self.api = Api()
|
|
153
158
|
self.logger = logger
|
|
154
159
|
|
|
File without changes
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Unit tests for AlienVault OTX integration functions
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import unittest.mock as mock
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from unittest.mock import MagicMock
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
import regscale.integrations.public.otx as otx
|
|
14
|
+
from regscale.integrations.public.otx import (
|
|
15
|
+
create_url,
|
|
16
|
+
extract_id,
|
|
17
|
+
walkapi_iter,
|
|
18
|
+
pulses,
|
|
19
|
+
SUBSCRIBED,
|
|
20
|
+
)
|
|
21
|
+
from regscale.models.regscale_models import Threat
|
|
22
|
+
from tests import CLITestFixture
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class TestAlienVaultOTX(CLITestFixture):
|
|
26
|
+
"""Test class for AlienVault OTX integration functions."""
|
|
27
|
+
|
|
28
|
+
def setup_walkapi_mocks(self, app_config=None):
|
|
29
|
+
"""Helper to create consistent walkapi_iter test setup."""
|
|
30
|
+
app = MagicMock()
|
|
31
|
+
app.config = app_config or {"otx": "KEY"}
|
|
32
|
+
app.logger = MagicMock()
|
|
33
|
+
api = MagicMock()
|
|
34
|
+
return app, api
|
|
35
|
+
|
|
36
|
+
def get_common_pulse_mocks(self):
|
|
37
|
+
"""Get standard mock patches for pulses() tests."""
|
|
38
|
+
return (
|
|
39
|
+
mock.patch.object(Threat, "fetch_all_threats", classmethod(lambda cls: [])),
|
|
40
|
+
mock.patch.object(Threat, "bulk_save", classmethod(lambda cls: None)),
|
|
41
|
+
mock.patch.object(
|
|
42
|
+
otx,
|
|
43
|
+
"Application",
|
|
44
|
+
side_effect=lambda: MagicMock(config={"otx": "KEY", "userId": "testuser"}, logger=MagicMock()),
|
|
45
|
+
),
|
|
46
|
+
mock.patch.object(otx, "Api", side_effect=lambda: MagicMock()),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
@pytest.mark.parametrize(
|
|
50
|
+
"input_path,kwargs,expected_contains,param_checks",
|
|
51
|
+
[
|
|
52
|
+
("/pulses", {}, "https://otx.alienvault.com/pulses", []),
|
|
53
|
+
("/pulses", {"a": 1, "b": "x"}, "https://otx.alienvault.com/pulses?", ["a=1", "b=x"]),
|
|
54
|
+
("http://example.com/data", {}, "http://example.com/data", []),
|
|
55
|
+
("http://example.com/data", {"foo": "bar"}, "http://example.com/data?", ["foo=bar"]),
|
|
56
|
+
],
|
|
57
|
+
)
|
|
58
|
+
def test_create_url(self, input_path, kwargs, expected_contains, param_checks):
|
|
59
|
+
"""Test URL creation with various inputs and parameters."""
|
|
60
|
+
result = create_url(input_path, **kwargs)
|
|
61
|
+
assert expected_contains in result
|
|
62
|
+
for param in param_checks:
|
|
63
|
+
assert param in result
|
|
64
|
+
|
|
65
|
+
@pytest.mark.parametrize(
|
|
66
|
+
"description,expected_result",
|
|
67
|
+
[
|
|
68
|
+
("Info AlienVault ID: ABC123 ...", "ABC123 ..."),
|
|
69
|
+
("no id here", ""),
|
|
70
|
+
("AlienVault ID: AAA and AlienVault ID: BBB", "AAA and AlienVault ID: BBB"),
|
|
71
|
+
("AlienVault ID: 12345", "12345"),
|
|
72
|
+
],
|
|
73
|
+
)
|
|
74
|
+
def test_extract_id(self, description, expected_result):
|
|
75
|
+
"""Test ID extraction from various description formats."""
|
|
76
|
+
result = extract_id(description)
|
|
77
|
+
assert result == expected_result
|
|
78
|
+
|
|
79
|
+
def test_walkapi_iter_pagination_and_errors(self):
|
|
80
|
+
"""Test that walkapi_iter paginates through results and handles authentication failures."""
|
|
81
|
+
page1 = {"count": 3, "results": [{"id": 1}, {"id": 2}], "next": "url2"}
|
|
82
|
+
page2 = {"count": 3, "results": [{"id": 3}], "next": None}
|
|
83
|
+
app, api = self.setup_walkapi_mocks()
|
|
84
|
+
api.get.side_effect = [
|
|
85
|
+
mock.MagicMock(ok=True, json=mock.MagicMock(return_value=page1)),
|
|
86
|
+
mock.MagicMock(ok=True, json=mock.MagicMock(return_value=page2)),
|
|
87
|
+
]
|
|
88
|
+
items = list(walkapi_iter(app, api, SUBSCRIBED, {"limit": 2}))
|
|
89
|
+
assert [i["id"] for i in items] == [1, 2, 3]
|
|
90
|
+
assert api.get.call_count == 2
|
|
91
|
+
auth_fail = mock.MagicMock(ok=True, json=mock.MagicMock(return_value={"detail": "Authentication required"}))
|
|
92
|
+
api.get.side_effect = [auth_fail]
|
|
93
|
+
with pytest.raises(ValueError):
|
|
94
|
+
next(walkapi_iter(app, api, SUBSCRIBED, {}))
|
|
95
|
+
|
|
96
|
+
def test_walkapi_iter_retries_on_error(self):
|
|
97
|
+
"""Test that walkapi_iter retries once if API.get raises UnboundLocalError."""
|
|
98
|
+
page = {"count": 1, "results": [{"id": 10}], "next": None}
|
|
99
|
+
app, api = self.setup_walkapi_mocks()
|
|
100
|
+
api.get.side_effect = [
|
|
101
|
+
UnboundLocalError("oops"),
|
|
102
|
+
mock.MagicMock(ok=True, json=mock.MagicMock(return_value=page)),
|
|
103
|
+
]
|
|
104
|
+
with mock.patch("time.sleep", return_value=None):
|
|
105
|
+
items = list(walkapi_iter(app, api, SUBSCRIBED, {"limit": 1}))
|
|
106
|
+
assert items == page["results"]
|
|
107
|
+
|
|
108
|
+
@pytest.mark.parametrize(
|
|
109
|
+
"modified_since,limit,expected_args",
|
|
110
|
+
[
|
|
111
|
+
(datetime(2022, 1, 2, 3, 4, 5), 8, {"limit": 8, "modified_since": "2022-01-02T03:04:05"}),
|
|
112
|
+
(None, 12, {"limit": 12}),
|
|
113
|
+
],
|
|
114
|
+
)
|
|
115
|
+
def test_pulses_parameter_handling(self, modified_since, limit, expected_args):
|
|
116
|
+
"""Test that pulses() correctly handles modified_since parameter."""
|
|
117
|
+
captured = {}
|
|
118
|
+
|
|
119
|
+
def fake_walk(app, api, url, args):
|
|
120
|
+
captured.update(args)
|
|
121
|
+
return iter([])
|
|
122
|
+
|
|
123
|
+
with mock.patch.object(otx, "walkapi_iter", side_effect=fake_walk), mock.patch.object(
|
|
124
|
+
Threat, "fetch_all_threats", classmethod(lambda cls: [])
|
|
125
|
+
), mock.patch.object(Threat, "bulk_save", classmethod(lambda cls: None)), mock.patch.object(
|
|
126
|
+
otx, "Application", side_effect=lambda: MagicMock(config={"otx": "KEY", "userId": "u"}, logger=MagicMock())
|
|
127
|
+
), mock.patch.object(
|
|
128
|
+
otx, "Api", side_effect=lambda: MagicMock()
|
|
129
|
+
):
|
|
130
|
+
pulses(modified_since, limit)
|
|
131
|
+
assert captured == expected_args
|
|
132
|
+
|
|
133
|
+
def run_pulses_test(self, pulse_data, existing_threats=None):
|
|
134
|
+
"""Helper to run pulses tests with common setup."""
|
|
135
|
+
created_threats = []
|
|
136
|
+
|
|
137
|
+
def mock_threat_create(self, bulk=False):
|
|
138
|
+
created_threats.append(self)
|
|
139
|
+
return self
|
|
140
|
+
|
|
141
|
+
threat_patches = list(self.get_common_pulse_mocks())
|
|
142
|
+
with threat_patches[0], threat_patches[1], threat_patches[2], threat_patches[3]:
|
|
143
|
+
with mock.patch.object(otx, "walkapi_iter", return_value=[pulse_data]), mock.patch.object(
|
|
144
|
+
Threat, "fetch_all_threats", classmethod(lambda cls: existing_threats or [])
|
|
145
|
+
), mock.patch.object(Threat, "create", mock_threat_create):
|
|
146
|
+
pulses(None, 10)
|
|
147
|
+
|
|
148
|
+
return created_threats
|
|
149
|
+
|
|
150
|
+
def test_pulses_threat_creation(self):
|
|
151
|
+
"""Test that pulses() creates threats correctly from API data."""
|
|
152
|
+
sample_pulse = {
|
|
153
|
+
"id": "12345",
|
|
154
|
+
"name": "Test Threat",
|
|
155
|
+
"description": "Test description",
|
|
156
|
+
"created": "2022-01-01T00:00:00",
|
|
157
|
+
"tags": ["malware", "trojan"],
|
|
158
|
+
"references": ["http://example.com"],
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
created_threats = self.run_pulses_test(sample_pulse)
|
|
162
|
+
assert len(created_threats) == 1
|
|
163
|
+
threat = created_threats[0]
|
|
164
|
+
assert threat.title == "Test Threat"
|
|
165
|
+
assert threat.description == "Test description\nhttps://otx.alienvault.com/pulse/12345"
|
|
166
|
+
assert "malware, trojan" in threat.notes
|
|
167
|
+
assert "AlienVault ID: 12345" in threat.notes
|
|
168
|
+
assert threat.threatOwnerId == "testuser"
|
|
169
|
+
|
|
170
|
+
def test_pulses_deduplication(self):
|
|
171
|
+
"""Test that pulses() avoids creating duplicate threats."""
|
|
172
|
+
sample_pulse = {
|
|
173
|
+
"id": "existing123",
|
|
174
|
+
"name": "Test Threat",
|
|
175
|
+
"description": "Test description",
|
|
176
|
+
"created": "2022-01-01T00:00:00",
|
|
177
|
+
"tags": ["malware"],
|
|
178
|
+
"references": [],
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
existing_threat = MagicMock()
|
|
182
|
+
existing_threat.notes = "Some notes\nAlienVault ID: existing123"
|
|
183
|
+
|
|
184
|
+
created_threats = self.run_pulses_test(sample_pulse, [existing_threat])
|
|
185
|
+
assert len(created_threats) == 0
|
|
186
|
+
|
|
187
|
+
def test_walkapi_iter_empty_response(self):
|
|
188
|
+
"""Test that walkapi_iter handles empty API responses."""
|
|
189
|
+
empty_page = {"count": 0, "results": [], "next": None}
|
|
190
|
+
app, api = self.setup_walkapi_mocks()
|
|
191
|
+
api.get.return_value = mock.MagicMock(ok=True, json=mock.MagicMock(return_value=empty_page))
|
|
192
|
+
|
|
193
|
+
items = list(walkapi_iter(app, api, SUBSCRIBED, {"limit": 10}))
|
|
194
|
+
assert items == []
|
|
195
|
+
|
|
196
|
+
def test_walkapi_iter_malformed_response(self):
|
|
197
|
+
"""Test that walkapi_iter handles responses missing required fields."""
|
|
198
|
+
malformed_page = {"results": [{"id": 1}]} # Missing 'count' and 'next'
|
|
199
|
+
app, api = self.setup_walkapi_mocks()
|
|
200
|
+
api.get.return_value = mock.MagicMock(ok=True, json=mock.MagicMock(return_value=malformed_page))
|
|
201
|
+
|
|
202
|
+
with pytest.raises(KeyError):
|
|
203
|
+
list(walkapi_iter(app, api, SUBSCRIBED, {"limit": 10}))
|
|
204
|
+
|
|
205
|
+
def test_pulses_handles_missing_references(self):
|
|
206
|
+
"""Test that pulses() handles API data missing optional references field."""
|
|
207
|
+
minimal_pulse = {
|
|
208
|
+
"id": "minimal123",
|
|
209
|
+
"name": "Minimal Threat",
|
|
210
|
+
"description": "Basic description",
|
|
211
|
+
"created": "2022-01-01T00:00:00",
|
|
212
|
+
"tags": ["minimal"],
|
|
213
|
+
# Missing 'references' - this is actually optional
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
created_threats = self.run_pulses_test(minimal_pulse)
|
|
217
|
+
assert len(created_threats) == 1
|
|
218
|
+
threat = created_threats[0]
|
|
219
|
+
assert "minimal \n" in threat.notes # Tags present, empty references
|
|
220
|
+
assert "AlienVault ID: minimal123" in threat.notes
|