regscale-cli 6.16.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/__init__.py +1 -0
- regscale/airflow/__init__.py +9 -0
- regscale/airflow/azure/__init__.py +9 -0
- regscale/airflow/azure/cli.py +89 -0
- regscale/airflow/azure/upload_dags.py +116 -0
- regscale/airflow/click_dags.py +127 -0
- regscale/airflow/click_mixins.py +82 -0
- regscale/airflow/config.py +25 -0
- regscale/airflow/factories/__init__.py +0 -0
- regscale/airflow/factories/connections.py +58 -0
- regscale/airflow/factories/workflows.py +78 -0
- regscale/airflow/hierarchy.py +88 -0
- regscale/airflow/operators/__init__.py +0 -0
- regscale/airflow/operators/click.py +36 -0
- regscale/airflow/sensors/__init__.py +0 -0
- regscale/airflow/sensors/sql.py +107 -0
- regscale/airflow/sessions/__init__.py +0 -0
- regscale/airflow/sessions/sql/__init__.py +3 -0
- regscale/airflow/sessions/sql/queries.py +64 -0
- regscale/airflow/sessions/sql/sql_server_queries.py +248 -0
- regscale/airflow/tasks/__init__.py +0 -0
- regscale/airflow/tasks/branches.py +22 -0
- regscale/airflow/tasks/cli.py +116 -0
- regscale/airflow/tasks/click.py +73 -0
- regscale/airflow/tasks/debugging.py +9 -0
- regscale/airflow/tasks/groups.py +116 -0
- regscale/airflow/tasks/init.py +60 -0
- regscale/airflow/tasks/states.py +47 -0
- regscale/airflow/tasks/workflows.py +36 -0
- regscale/ansible/__init__.py +9 -0
- regscale/core/__init__.py +0 -0
- regscale/core/app/__init__.py +3 -0
- regscale/core/app/api.py +571 -0
- regscale/core/app/application.py +665 -0
- regscale/core/app/internal/__init__.py +136 -0
- regscale/core/app/internal/admin_actions.py +230 -0
- regscale/core/app/internal/assessments_editor.py +873 -0
- regscale/core/app/internal/catalog.py +316 -0
- regscale/core/app/internal/comparison.py +459 -0
- regscale/core/app/internal/control_editor.py +571 -0
- regscale/core/app/internal/encrypt.py +79 -0
- regscale/core/app/internal/evidence.py +1240 -0
- regscale/core/app/internal/file_uploads.py +151 -0
- regscale/core/app/internal/healthcheck.py +66 -0
- regscale/core/app/internal/login.py +305 -0
- regscale/core/app/internal/migrations.py +240 -0
- regscale/core/app/internal/model_editor.py +1701 -0
- regscale/core/app/internal/poam_editor.py +632 -0
- regscale/core/app/internal/workflow.py +105 -0
- regscale/core/app/logz.py +74 -0
- regscale/core/app/utils/XMLIR.py +258 -0
- regscale/core/app/utils/__init__.py +0 -0
- regscale/core/app/utils/api_handler.py +358 -0
- regscale/core/app/utils/app_utils.py +1110 -0
- regscale/core/app/utils/catalog_utils/__init__.py +0 -0
- regscale/core/app/utils/catalog_utils/common.py +91 -0
- regscale/core/app/utils/catalog_utils/compare_catalog.py +193 -0
- regscale/core/app/utils/catalog_utils/diagnostic_catalog.py +97 -0
- regscale/core/app/utils/catalog_utils/download_catalog.py +103 -0
- regscale/core/app/utils/catalog_utils/update_catalog.py +718 -0
- regscale/core/app/utils/catalog_utils/update_catalog_v2.py +1378 -0
- regscale/core/app/utils/catalog_utils/update_catalog_v3.py +1272 -0
- regscale/core/app/utils/catalog_utils/update_plans.py +334 -0
- regscale/core/app/utils/file_utils.py +238 -0
- regscale/core/app/utils/parser_utils.py +81 -0
- regscale/core/app/utils/pickle_file_handler.py +57 -0
- regscale/core/app/utils/regscale_utils.py +319 -0
- regscale/core/app/utils/report_utils.py +119 -0
- regscale/core/app/utils/variables.py +226 -0
- regscale/core/decorators.py +31 -0
- regscale/core/lazy_group.py +65 -0
- regscale/core/login.py +63 -0
- regscale/core/server/__init__.py +0 -0
- regscale/core/server/flask_api.py +473 -0
- regscale/core/server/helpers.py +373 -0
- regscale/core/server/rest.py +64 -0
- regscale/core/server/static/css/bootstrap.css +6030 -0
- regscale/core/server/static/css/bootstrap.min.css +6 -0
- regscale/core/server/static/css/main.css +176 -0
- regscale/core/server/static/images/regscale-cli.svg +49 -0
- regscale/core/server/static/images/regscale.svg +38 -0
- regscale/core/server/templates/base.html +74 -0
- regscale/core/server/templates/index.html +43 -0
- regscale/core/server/templates/login.html +28 -0
- regscale/core/server/templates/make_base64.html +22 -0
- regscale/core/server/templates/upload_STIG.html +109 -0
- regscale/core/server/templates/upload_STIG_result.html +26 -0
- regscale/core/server/templates/upload_ssp.html +144 -0
- regscale/core/server/templates/upload_ssp_result.html +128 -0
- regscale/core/static/__init__.py +0 -0
- regscale/core/static/regex.py +14 -0
- regscale/core/utils/__init__.py +117 -0
- regscale/core/utils/click_utils.py +13 -0
- regscale/core/utils/date.py +238 -0
- regscale/core/utils/graphql.py +254 -0
- regscale/core/utils/urls.py +23 -0
- regscale/dev/__init__.py +6 -0
- regscale/dev/analysis.py +454 -0
- regscale/dev/cli.py +235 -0
- regscale/dev/code_gen.py +492 -0
- regscale/dev/dirs.py +69 -0
- regscale/dev/docs.py +384 -0
- regscale/dev/monitoring.py +26 -0
- regscale/dev/profiling.py +216 -0
- regscale/exceptions/__init__.py +4 -0
- regscale/exceptions/license_exception.py +7 -0
- regscale/exceptions/validation_exception.py +9 -0
- regscale/integrations/__init__.py +1 -0
- regscale/integrations/commercial/__init__.py +486 -0
- regscale/integrations/commercial/ad.py +433 -0
- regscale/integrations/commercial/amazon/__init__.py +0 -0
- regscale/integrations/commercial/amazon/common.py +106 -0
- regscale/integrations/commercial/aqua/__init__.py +0 -0
- regscale/integrations/commercial/aqua/aqua.py +91 -0
- regscale/integrations/commercial/aws/__init__.py +6 -0
- regscale/integrations/commercial/aws/cli.py +322 -0
- regscale/integrations/commercial/aws/inventory/__init__.py +110 -0
- regscale/integrations/commercial/aws/inventory/base.py +64 -0
- regscale/integrations/commercial/aws/inventory/resources/__init__.py +19 -0
- regscale/integrations/commercial/aws/inventory/resources/compute.py +234 -0
- regscale/integrations/commercial/aws/inventory/resources/containers.py +113 -0
- regscale/integrations/commercial/aws/inventory/resources/database.py +101 -0
- regscale/integrations/commercial/aws/inventory/resources/integration.py +237 -0
- regscale/integrations/commercial/aws/inventory/resources/networking.py +253 -0
- regscale/integrations/commercial/aws/inventory/resources/security.py +240 -0
- regscale/integrations/commercial/aws/inventory/resources/storage.py +91 -0
- regscale/integrations/commercial/aws/scanner.py +823 -0
- regscale/integrations/commercial/azure/__init__.py +0 -0
- regscale/integrations/commercial/azure/common.py +32 -0
- regscale/integrations/commercial/azure/intune.py +488 -0
- regscale/integrations/commercial/azure/scanner.py +49 -0
- regscale/integrations/commercial/burp.py +78 -0
- regscale/integrations/commercial/cpe.py +144 -0
- regscale/integrations/commercial/crowdstrike.py +1117 -0
- regscale/integrations/commercial/defender.py +1511 -0
- regscale/integrations/commercial/dependabot.py +210 -0
- regscale/integrations/commercial/durosuite/__init__.py +0 -0
- regscale/integrations/commercial/durosuite/api.py +1546 -0
- regscale/integrations/commercial/durosuite/process_devices.py +101 -0
- regscale/integrations/commercial/durosuite/scanner.py +637 -0
- regscale/integrations/commercial/durosuite/variables.py +21 -0
- regscale/integrations/commercial/ecr.py +90 -0
- regscale/integrations/commercial/gcp/__init__.py +237 -0
- regscale/integrations/commercial/gcp/auth.py +96 -0
- regscale/integrations/commercial/gcp/control_tests.py +238 -0
- regscale/integrations/commercial/gcp/variables.py +18 -0
- regscale/integrations/commercial/gitlab.py +332 -0
- regscale/integrations/commercial/grype.py +165 -0
- regscale/integrations/commercial/ibm.py +90 -0
- regscale/integrations/commercial/import_all/__init__.py +0 -0
- regscale/integrations/commercial/import_all/import_all_cmd.py +467 -0
- regscale/integrations/commercial/import_all/scan_file_fingerprints.json +27 -0
- regscale/integrations/commercial/jira.py +1046 -0
- regscale/integrations/commercial/mappings/__init__.py +0 -0
- regscale/integrations/commercial/mappings/csf_controls.json +713 -0
- regscale/integrations/commercial/mappings/nist_800_53_r5_controls.json +1516 -0
- regscale/integrations/commercial/nessus/__init__.py +0 -0
- regscale/integrations/commercial/nessus/nessus_utils.py +429 -0
- regscale/integrations/commercial/nessus/scanner.py +416 -0
- regscale/integrations/commercial/nexpose.py +90 -0
- regscale/integrations/commercial/okta.py +798 -0
- regscale/integrations/commercial/opentext/__init__.py +0 -0
- regscale/integrations/commercial/opentext/click.py +99 -0
- regscale/integrations/commercial/opentext/scanner.py +143 -0
- regscale/integrations/commercial/prisma.py +91 -0
- regscale/integrations/commercial/qualys.py +1462 -0
- regscale/integrations/commercial/salesforce.py +980 -0
- regscale/integrations/commercial/sap/__init__.py +0 -0
- regscale/integrations/commercial/sap/click.py +31 -0
- regscale/integrations/commercial/sap/sysdig/__init__.py +0 -0
- regscale/integrations/commercial/sap/sysdig/click.py +57 -0
- regscale/integrations/commercial/sap/sysdig/sysdig_scanner.py +190 -0
- regscale/integrations/commercial/sap/tenable/__init__.py +0 -0
- regscale/integrations/commercial/sap/tenable/click.py +49 -0
- regscale/integrations/commercial/sap/tenable/scanner.py +196 -0
- regscale/integrations/commercial/servicenow.py +1756 -0
- regscale/integrations/commercial/sicura/__init__.py +0 -0
- regscale/integrations/commercial/sicura/api.py +855 -0
- regscale/integrations/commercial/sicura/commands.py +73 -0
- regscale/integrations/commercial/sicura/scanner.py +481 -0
- regscale/integrations/commercial/sicura/variables.py +16 -0
- regscale/integrations/commercial/snyk.py +90 -0
- regscale/integrations/commercial/sonarcloud.py +260 -0
- regscale/integrations/commercial/sqlserver.py +369 -0
- regscale/integrations/commercial/stig_mapper_integration/__init__.py +0 -0
- regscale/integrations/commercial/stig_mapper_integration/click_commands.py +38 -0
- regscale/integrations/commercial/stig_mapper_integration/mapping_engine.py +353 -0
- regscale/integrations/commercial/stigv2/__init__.py +0 -0
- regscale/integrations/commercial/stigv2/ckl_parser.py +349 -0
- regscale/integrations/commercial/stigv2/click_commands.py +95 -0
- regscale/integrations/commercial/stigv2/stig_integration.py +202 -0
- regscale/integrations/commercial/synqly/__init__.py +0 -0
- regscale/integrations/commercial/synqly/assets.py +46 -0
- regscale/integrations/commercial/synqly/ticketing.py +132 -0
- regscale/integrations/commercial/synqly/vulnerabilities.py +223 -0
- regscale/integrations/commercial/synqly_jira.py +840 -0
- regscale/integrations/commercial/tenablev2/__init__.py +0 -0
- regscale/integrations/commercial/tenablev2/authenticate.py +31 -0
- regscale/integrations/commercial/tenablev2/click.py +1584 -0
- regscale/integrations/commercial/tenablev2/scanner.py +504 -0
- regscale/integrations/commercial/tenablev2/stig_parsers.py +140 -0
- regscale/integrations/commercial/tenablev2/utils.py +78 -0
- regscale/integrations/commercial/tenablev2/variables.py +17 -0
- regscale/integrations/commercial/trivy.py +162 -0
- regscale/integrations/commercial/veracode.py +96 -0
- regscale/integrations/commercial/wizv2/WizDataMixin.py +97 -0
- regscale/integrations/commercial/wizv2/__init__.py +0 -0
- regscale/integrations/commercial/wizv2/click.py +429 -0
- regscale/integrations/commercial/wizv2/constants.py +1001 -0
- regscale/integrations/commercial/wizv2/issue.py +361 -0
- regscale/integrations/commercial/wizv2/models.py +112 -0
- regscale/integrations/commercial/wizv2/parsers.py +339 -0
- regscale/integrations/commercial/wizv2/sbom.py +115 -0
- regscale/integrations/commercial/wizv2/scanner.py +416 -0
- regscale/integrations/commercial/wizv2/utils.py +796 -0
- regscale/integrations/commercial/wizv2/variables.py +39 -0
- regscale/integrations/commercial/wizv2/wiz_auth.py +159 -0
- regscale/integrations/commercial/xray.py +91 -0
- regscale/integrations/integration/__init__.py +2 -0
- regscale/integrations/integration/integration.py +26 -0
- regscale/integrations/integration/inventory.py +17 -0
- regscale/integrations/integration/issue.py +100 -0
- regscale/integrations/integration_override.py +149 -0
- regscale/integrations/public/__init__.py +103 -0
- regscale/integrations/public/cisa.py +641 -0
- regscale/integrations/public/criticality_updater.py +70 -0
- regscale/integrations/public/emass.py +411 -0
- regscale/integrations/public/emass_slcm_import.py +697 -0
- regscale/integrations/public/fedramp/__init__.py +0 -0
- regscale/integrations/public/fedramp/appendix_parser.py +548 -0
- regscale/integrations/public/fedramp/click.py +479 -0
- regscale/integrations/public/fedramp/components.py +714 -0
- regscale/integrations/public/fedramp/docx_parser.py +259 -0
- regscale/integrations/public/fedramp/fedramp_cis_crm.py +1124 -0
- regscale/integrations/public/fedramp/fedramp_common.py +3181 -0
- regscale/integrations/public/fedramp/fedramp_docx.py +388 -0
- regscale/integrations/public/fedramp/fedramp_five.py +2343 -0
- regscale/integrations/public/fedramp/fedramp_traversal.py +138 -0
- regscale/integrations/public/fedramp/import_fedramp_r4_ssp.py +279 -0
- regscale/integrations/public/fedramp/import_workbook.py +495 -0
- regscale/integrations/public/fedramp/inventory_items.py +244 -0
- regscale/integrations/public/fedramp/mappings/__init__.py +0 -0
- regscale/integrations/public/fedramp/mappings/fedramp_r4_parts.json +7388 -0
- regscale/integrations/public/fedramp/mappings/fedramp_r5_params.json +8636 -0
- regscale/integrations/public/fedramp/mappings/fedramp_r5_parts.json +9605 -0
- regscale/integrations/public/fedramp/mappings/system_roles.py +34 -0
- regscale/integrations/public/fedramp/mappings/user.py +175 -0
- regscale/integrations/public/fedramp/mappings/values.py +141 -0
- regscale/integrations/public/fedramp/markdown_parser.py +150 -0
- regscale/integrations/public/fedramp/metadata.py +689 -0
- regscale/integrations/public/fedramp/models/__init__.py +59 -0
- regscale/integrations/public/fedramp/models/leveraged_auth_new.py +168 -0
- regscale/integrations/public/fedramp/models/poam_importer.py +522 -0
- regscale/integrations/public/fedramp/parts_mapper.py +107 -0
- regscale/integrations/public/fedramp/poam/__init__.py +0 -0
- regscale/integrations/public/fedramp/poam/scanner.py +851 -0
- regscale/integrations/public/fedramp/properties.py +201 -0
- regscale/integrations/public/fedramp/reporting.py +84 -0
- regscale/integrations/public/fedramp/resources.py +496 -0
- regscale/integrations/public/fedramp/rosetta.py +110 -0
- regscale/integrations/public/fedramp/ssp_logger.py +87 -0
- regscale/integrations/public/fedramp/system_characteristics.py +922 -0
- regscale/integrations/public/fedramp/system_control_implementations.py +582 -0
- regscale/integrations/public/fedramp/system_implementation.py +190 -0
- regscale/integrations/public/fedramp/xml_utils.py +87 -0
- regscale/integrations/public/nist_catalog.py +275 -0
- regscale/integrations/public/oscal.py +1946 -0
- regscale/integrations/public/otx.py +169 -0
- regscale/integrations/scanner_integration.py +2692 -0
- regscale/integrations/variables.py +25 -0
- regscale/models/__init__.py +7 -0
- regscale/models/app_models/__init__.py +5 -0
- regscale/models/app_models/catalog_compare.py +213 -0
- regscale/models/app_models/click.py +252 -0
- regscale/models/app_models/datetime_encoder.py +21 -0
- regscale/models/app_models/import_validater.py +321 -0
- regscale/models/app_models/mapping.py +260 -0
- regscale/models/app_models/pipeline.py +37 -0
- regscale/models/click_models.py +413 -0
- regscale/models/config.py +154 -0
- regscale/models/email_style.css +67 -0
- regscale/models/hierarchy.py +8 -0
- regscale/models/inspect_models.py +79 -0
- regscale/models/integration_models/__init__.py +0 -0
- regscale/models/integration_models/amazon_models/__init__.py +0 -0
- regscale/models/integration_models/amazon_models/inspector.py +262 -0
- regscale/models/integration_models/amazon_models/inspector_scan.py +206 -0
- regscale/models/integration_models/aqua.py +247 -0
- regscale/models/integration_models/azure_alerts.py +255 -0
- regscale/models/integration_models/base64.py +23 -0
- regscale/models/integration_models/burp.py +433 -0
- regscale/models/integration_models/burp_models.py +128 -0
- regscale/models/integration_models/cisa_kev_data.json +19333 -0
- regscale/models/integration_models/defender_data.py +93 -0
- regscale/models/integration_models/defenderimport.py +143 -0
- regscale/models/integration_models/drf.py +443 -0
- regscale/models/integration_models/ecr_models/__init__.py +0 -0
- regscale/models/integration_models/ecr_models/data.py +69 -0
- regscale/models/integration_models/ecr_models/ecr.py +239 -0
- regscale/models/integration_models/flat_file_importer.py +1079 -0
- regscale/models/integration_models/grype_import.py +247 -0
- regscale/models/integration_models/ibm.py +126 -0
- regscale/models/integration_models/implementation_results.py +85 -0
- regscale/models/integration_models/nexpose.py +140 -0
- regscale/models/integration_models/prisma.py +202 -0
- regscale/models/integration_models/qualys.py +720 -0
- regscale/models/integration_models/qualys_scanner.py +160 -0
- regscale/models/integration_models/sbom/__init__.py +0 -0
- regscale/models/integration_models/sbom/cyclone_dx.py +139 -0
- regscale/models/integration_models/send_reminders.py +620 -0
- regscale/models/integration_models/snyk.py +155 -0
- regscale/models/integration_models/synqly_models/__init__.py +0 -0
- regscale/models/integration_models/synqly_models/capabilities.json +1 -0
- regscale/models/integration_models/synqly_models/connector_types.py +22 -0
- regscale/models/integration_models/synqly_models/connectors/__init__.py +7 -0
- regscale/models/integration_models/synqly_models/connectors/assets.py +97 -0
- regscale/models/integration_models/synqly_models/connectors/ticketing.py +583 -0
- regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +169 -0
- regscale/models/integration_models/synqly_models/ocsf_mapper.py +331 -0
- regscale/models/integration_models/synqly_models/param.py +72 -0
- regscale/models/integration_models/synqly_models/synqly_model.py +733 -0
- regscale/models/integration_models/synqly_models/tenants.py +39 -0
- regscale/models/integration_models/tenable_models/__init__.py +0 -0
- regscale/models/integration_models/tenable_models/integration.py +187 -0
- regscale/models/integration_models/tenable_models/models.py +513 -0
- regscale/models/integration_models/trivy_import.py +231 -0
- regscale/models/integration_models/veracode.py +217 -0
- regscale/models/integration_models/xray.py +135 -0
- regscale/models/locking.py +100 -0
- regscale/models/platform.py +110 -0
- regscale/models/regscale_models/__init__.py +67 -0
- regscale/models/regscale_models/assessment.py +570 -0
- regscale/models/regscale_models/assessment_plan.py +52 -0
- regscale/models/regscale_models/asset.py +567 -0
- regscale/models/regscale_models/asset_mapping.py +190 -0
- regscale/models/regscale_models/case.py +42 -0
- regscale/models/regscale_models/catalog.py +261 -0
- regscale/models/regscale_models/cci.py +46 -0
- regscale/models/regscale_models/change.py +167 -0
- regscale/models/regscale_models/checklist.py +372 -0
- regscale/models/regscale_models/comment.py +49 -0
- regscale/models/regscale_models/compliance_settings.py +112 -0
- regscale/models/regscale_models/component.py +412 -0
- regscale/models/regscale_models/component_mapping.py +65 -0
- regscale/models/regscale_models/control.py +38 -0
- regscale/models/regscale_models/control_implementation.py +1128 -0
- regscale/models/regscale_models/control_objective.py +261 -0
- regscale/models/regscale_models/control_parameter.py +100 -0
- regscale/models/regscale_models/control_test.py +34 -0
- regscale/models/regscale_models/control_test_plan.py +75 -0
- regscale/models/regscale_models/control_test_result.py +52 -0
- regscale/models/regscale_models/custom_field.py +245 -0
- regscale/models/regscale_models/data.py +109 -0
- regscale/models/regscale_models/data_center.py +40 -0
- regscale/models/regscale_models/deviation.py +203 -0
- regscale/models/regscale_models/email.py +97 -0
- regscale/models/regscale_models/evidence.py +47 -0
- regscale/models/regscale_models/evidence_mapping.py +40 -0
- regscale/models/regscale_models/facility.py +59 -0
- regscale/models/regscale_models/file.py +382 -0
- regscale/models/regscale_models/filetag.py +37 -0
- regscale/models/regscale_models/form_field_value.py +94 -0
- regscale/models/regscale_models/group.py +169 -0
- regscale/models/regscale_models/implementation_objective.py +335 -0
- regscale/models/regscale_models/implementation_option.py +275 -0
- regscale/models/regscale_models/implementation_role.py +33 -0
- regscale/models/regscale_models/incident.py +177 -0
- regscale/models/regscale_models/interconnection.py +43 -0
- regscale/models/regscale_models/issue.py +1176 -0
- regscale/models/regscale_models/leveraged_authorization.py +125 -0
- regscale/models/regscale_models/line_of_inquiry.py +52 -0
- regscale/models/regscale_models/link.py +205 -0
- regscale/models/regscale_models/meta_data.py +64 -0
- regscale/models/regscale_models/mixins/__init__.py +0 -0
- regscale/models/regscale_models/mixins/parent_cache.py +124 -0
- regscale/models/regscale_models/module.py +224 -0
- regscale/models/regscale_models/modules.py +191 -0
- regscale/models/regscale_models/objective.py +14 -0
- regscale/models/regscale_models/parameter.py +87 -0
- regscale/models/regscale_models/ports_protocol.py +81 -0
- regscale/models/regscale_models/privacy.py +89 -0
- regscale/models/regscale_models/profile.py +50 -0
- regscale/models/regscale_models/profile_link.py +68 -0
- regscale/models/regscale_models/profile_mapping.py +124 -0
- regscale/models/regscale_models/project.py +63 -0
- regscale/models/regscale_models/property.py +278 -0
- regscale/models/regscale_models/question.py +85 -0
- regscale/models/regscale_models/questionnaire.py +87 -0
- regscale/models/regscale_models/questionnaire_instance.py +177 -0
- regscale/models/regscale_models/rbac.py +132 -0
- regscale/models/regscale_models/reference.py +86 -0
- regscale/models/regscale_models/regscale_model.py +1643 -0
- regscale/models/regscale_models/requirement.py +29 -0
- regscale/models/regscale_models/risk.py +274 -0
- regscale/models/regscale_models/sbom.py +54 -0
- regscale/models/regscale_models/scan_history.py +436 -0
- regscale/models/regscale_models/search.py +53 -0
- regscale/models/regscale_models/security_control.py +132 -0
- regscale/models/regscale_models/security_plan.py +204 -0
- regscale/models/regscale_models/software_inventory.py +159 -0
- regscale/models/regscale_models/stake_holder.py +64 -0
- regscale/models/regscale_models/stig.py +647 -0
- regscale/models/regscale_models/supply_chain.py +152 -0
- regscale/models/regscale_models/system_role.py +188 -0
- regscale/models/regscale_models/system_role_external_assignment.py +40 -0
- regscale/models/regscale_models/tag.py +37 -0
- regscale/models/regscale_models/tag_mapping.py +19 -0
- regscale/models/regscale_models/task.py +133 -0
- regscale/models/regscale_models/threat.py +196 -0
- regscale/models/regscale_models/user.py +175 -0
- regscale/models/regscale_models/user_group.py +55 -0
- regscale/models/regscale_models/vulnerability.py +242 -0
- regscale/models/regscale_models/vulnerability_mapping.py +162 -0
- regscale/models/regscale_models/workflow.py +55 -0
- regscale/models/regscale_models/workflow_action.py +34 -0
- regscale/models/regscale_models/workflow_instance.py +269 -0
- regscale/models/regscale_models/workflow_instance_step.py +114 -0
- regscale/models/regscale_models/workflow_template.py +58 -0
- regscale/models/regscale_models/workflow_template_step.py +45 -0
- regscale/regscale.py +815 -0
- regscale/utils/__init__.py +7 -0
- regscale/utils/b64conversion.py +14 -0
- regscale/utils/click_utils.py +118 -0
- regscale/utils/decorators.py +48 -0
- regscale/utils/dict_utils.py +59 -0
- regscale/utils/files.py +79 -0
- regscale/utils/fxns.py +30 -0
- regscale/utils/graphql_client.py +113 -0
- regscale/utils/lists.py +16 -0
- regscale/utils/numbers.py +12 -0
- regscale/utils/shell.py +148 -0
- regscale/utils/string.py +121 -0
- regscale/utils/synqly_utils.py +165 -0
- regscale/utils/threading/__init__.py +8 -0
- regscale/utils/threading/threadhandler.py +131 -0
- regscale/utils/threading/threadsafe_counter.py +47 -0
- regscale/utils/threading/threadsafe_dict.py +242 -0
- regscale/utils/threading/threadsafe_list.py +83 -0
- regscale/utils/version.py +104 -0
- regscale/validation/__init__.py +0 -0
- regscale/validation/address.py +37 -0
- regscale/validation/record.py +48 -0
- regscale/visualization/__init__.py +5 -0
- regscale/visualization/click.py +34 -0
- regscale_cli-6.16.0.0.dist-info/LICENSE +21 -0
- regscale_cli-6.16.0.0.dist-info/METADATA +659 -0
- regscale_cli-6.16.0.0.dist-info/RECORD +481 -0
- regscale_cli-6.16.0.0.dist-info/WHEEL +5 -0
- regscale_cli-6.16.0.0.dist-info/entry_points.txt +6 -0
- regscale_cli-6.16.0.0.dist-info/top_level.txt +2 -0
- tests/fixtures/__init__.py +2 -0
- tests/fixtures/api.py +87 -0
- tests/fixtures/models.py +91 -0
- tests/fixtures/test_fixture.py +144 -0
- tests/mocks/__init__.py +0 -0
- tests/mocks/objects.py +3 -0
- tests/mocks/response.py +32 -0
- tests/mocks/xml.py +13 -0
- tests/regscale/__init__.py +0 -0
- tests/regscale/core/__init__.py +0 -0
- tests/regscale/core/test_api.py +232 -0
- tests/regscale/core/test_app.py +406 -0
- tests/regscale/core/test_login.py +37 -0
- tests/regscale/core/test_logz.py +66 -0
- tests/regscale/core/test_sbom_generator.py +87 -0
- tests/regscale/core/test_validation_utils.py +163 -0
- tests/regscale/core/test_version.py +78 -0
- tests/regscale/models/__init__.py +0 -0
- tests/regscale/models/test_asset.py +71 -0
- tests/regscale/models/test_config.py +26 -0
- tests/regscale/models/test_control_implementation.py +27 -0
- tests/regscale/models/test_import.py +97 -0
- tests/regscale/models/test_issue.py +36 -0
- tests/regscale/models/test_mapping.py +52 -0
- tests/regscale/models/test_platform.py +31 -0
- tests/regscale/models/test_regscale_model.py +346 -0
- tests/regscale/models/test_report.py +32 -0
- tests/regscale/models/test_tenable_integrations.py +118 -0
- tests/regscale/models/test_user_model.py +121 -0
- tests/regscale/test_about.py +19 -0
- tests/regscale/test_authorization.py +65 -0
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Pydantic model for a Burp Scan"""
|
|
4
|
+
import os
|
|
5
|
+
import re
|
|
6
|
+
import shutil
|
|
7
|
+
from datetime import datetime, timedelta
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any, Generator, List, Optional, TextIO
|
|
10
|
+
from urllib.parse import urlparse
|
|
11
|
+
from xml.etree.ElementTree import Element, ParseError, fromstring, parse
|
|
12
|
+
|
|
13
|
+
from regscale.core.app.api import Api
|
|
14
|
+
from regscale.core.app.application import Application
|
|
15
|
+
from regscale.core.app.logz import create_logger
|
|
16
|
+
from regscale.core.app.utils.app_utils import check_file_path, get_current_datetime
|
|
17
|
+
from regscale.integrations.scanner_integration import IntegrationAsset, IntegrationFinding
|
|
18
|
+
from regscale.models.integration_models.burp_models import BurpRequest, BurpResponse, Issue, RequestResponse
|
|
19
|
+
from regscale.models.regscale_models import File
|
|
20
|
+
from regscale.models.regscale_models import Issue as RegscaleIssue
|
|
21
|
+
|
|
22
|
+
# standard python imports
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Burp:
|
|
26
|
+
"""Burp Scan information"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, app: Application, file_path: str, encoding="utf-8", **kwargs) -> "Burp":
|
|
29
|
+
logger = create_logger("Burp")
|
|
30
|
+
logger.info("Now processing %s", file_path)
|
|
31
|
+
self.integration_assets: Generator[IntegrationAsset, None, None] = (x for x in [])
|
|
32
|
+
self.integration_findings: Generator[IntegrationFinding, None, None] = (x for x in [])
|
|
33
|
+
self.num_assets = 0
|
|
34
|
+
self.num_findings = 0
|
|
35
|
+
self.job_complete = False
|
|
36
|
+
self.logger = logger
|
|
37
|
+
self.app = app
|
|
38
|
+
self.api = Api()
|
|
39
|
+
self.parent_id = 0
|
|
40
|
+
self.parent_module = "assets"
|
|
41
|
+
if "parentId" in kwargs and kwargs["parentId"]:
|
|
42
|
+
self.parent_id = kwargs["parentId"]
|
|
43
|
+
if "parentModule" in kwargs and kwargs["parentModule"]:
|
|
44
|
+
self.parent_module = kwargs["parentModule"]
|
|
45
|
+
self.encoding = encoding
|
|
46
|
+
self.file_path = Path(file_path)
|
|
47
|
+
self.version = None
|
|
48
|
+
self.export_time = None
|
|
49
|
+
self.burp_issues = []
|
|
50
|
+
self.existing_issues = []
|
|
51
|
+
self.from_file()
|
|
52
|
+
|
|
53
|
+
def move_files(self, upload_file: Optional[bool] = True) -> None:
|
|
54
|
+
"""
|
|
55
|
+
Move files to processed directory and upload to RegScale after processing
|
|
56
|
+
|
|
57
|
+
:param Optional[bool] upload_file: Whether to upload the file to RegScale after processing. Default is True.
|
|
58
|
+
:rtype: None
|
|
59
|
+
"""
|
|
60
|
+
api = Api()
|
|
61
|
+
# Create processed directory if it doesn't exist, and copy file to it.
|
|
62
|
+
|
|
63
|
+
new_file_path: Path = Path()
|
|
64
|
+
processed_dir = self.file_path.parent / "processed"
|
|
65
|
+
check_file_path(str(processed_dir.absolute()))
|
|
66
|
+
try:
|
|
67
|
+
if self.parent_id and self.job_complete:
|
|
68
|
+
file_name = f"{self.file_path.stem}_{get_current_datetime('%Y%m%d-%I%M%S%p')}".replace(" ", "_")
|
|
69
|
+
# Rename to friendly file name and post to Regscale
|
|
70
|
+
new_file_path = self.file_path.rename(self.file_path.parent / (file_name + ".xml"))
|
|
71
|
+
self.logger.info(
|
|
72
|
+
"Renaming %s to %s...",
|
|
73
|
+
self.file_path.name,
|
|
74
|
+
new_file_path.name,
|
|
75
|
+
)
|
|
76
|
+
if upload_file and File.upload_file_to_regscale(
|
|
77
|
+
file_name=str(new_file_path.absolute()),
|
|
78
|
+
parent_id=self.parent_id,
|
|
79
|
+
parent_module="securityplans",
|
|
80
|
+
api=api,
|
|
81
|
+
):
|
|
82
|
+
self.logger.info("Uploaded %s to RegScale securityplans #%i.", new_file_path.name, self.parent_id)
|
|
83
|
+
shutil.move(new_file_path, processed_dir)
|
|
84
|
+
try:
|
|
85
|
+
# Clean up the gzipped file created
|
|
86
|
+
os.remove(new_file_path.with_suffix(".gz"))
|
|
87
|
+
except FileNotFoundError:
|
|
88
|
+
self.logger.debug(
|
|
89
|
+
"File %s already exists in %s",
|
|
90
|
+
new_file_path.with_suffix(".gz").name,
|
|
91
|
+
processed_dir,
|
|
92
|
+
)
|
|
93
|
+
except shutil.Error:
|
|
94
|
+
self.logger.debug(
|
|
95
|
+
"File %s already exists in %s",
|
|
96
|
+
new_file_path.name,
|
|
97
|
+
processed_dir,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
def from_file(self) -> None:
|
|
101
|
+
"""
|
|
102
|
+
Read Burp Scan file
|
|
103
|
+
|
|
104
|
+
:rtype: None
|
|
105
|
+
"""
|
|
106
|
+
self.logger.debug(os.getcwd())
|
|
107
|
+
try:
|
|
108
|
+
with open(file=self.file_path, mode="r", encoding=self.encoding) as file:
|
|
109
|
+
root = self.file_root_element(file)
|
|
110
|
+
self.version = root.attrib["burpVersion"]
|
|
111
|
+
self.export_time = root.attrib["exportTime"]
|
|
112
|
+
self.gen_findings(root)
|
|
113
|
+
self.gen_assets()
|
|
114
|
+
self.job_complete = True
|
|
115
|
+
except (FileNotFoundError, ParseError):
|
|
116
|
+
self.logger.error("File not found: %s", self.file_path)
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def file_root_element(file: TextIO) -> Element:
|
|
120
|
+
"""
|
|
121
|
+
Function returns the root element for tree of given file with scan results
|
|
122
|
+
|
|
123
|
+
:param TextIO file: file with scan results
|
|
124
|
+
:return: root element for this tree
|
|
125
|
+
:rtype: Element
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
scan_file_parsed = parse(file)
|
|
129
|
+
root = scan_file_parsed.getroot()
|
|
130
|
+
return root
|
|
131
|
+
|
|
132
|
+
def create_issue(self, xml: Element) -> Issue:
|
|
133
|
+
"""
|
|
134
|
+
Create an issue from the XML
|
|
135
|
+
|
|
136
|
+
:param Element xml: XML
|
|
137
|
+
:return: Issue object from XML
|
|
138
|
+
:rtype: Issue
|
|
139
|
+
"""
|
|
140
|
+
issue = Issue()
|
|
141
|
+
issue.serialNumber = self.get(xml, "serialNumber")
|
|
142
|
+
issue.type = self.get(xml, "type")
|
|
143
|
+
issue.host = self.get_domain_name(self.get(xml, "host"))
|
|
144
|
+
issue.path = self.get(xml, "path")
|
|
145
|
+
issue.name = self.get(xml, "name")
|
|
146
|
+
issue.location = self.get(xml, "location")
|
|
147
|
+
issue.severity = self.get(xml, "severity")
|
|
148
|
+
issue.confidence = self.get(xml, "confidence")
|
|
149
|
+
issue.background = self.strip_html_tags(self.get(xml, "issueBackground"))
|
|
150
|
+
issue.detail = self.get(xml, "issueDetail")
|
|
151
|
+
issue.remediation_background = self.strip_html_tags(self.get(xml, "remediationBackground"))
|
|
152
|
+
issue.remediation_detail = self.strip_html_tags(self.get(xml, "remediationDetail"))
|
|
153
|
+
issue.links = self.extract_links(self.get(xml, "vulnerabilityClassifications"))
|
|
154
|
+
issue.cwes = self.extract_classifications(self.get(xml, "vulnerabilityClassifications"))
|
|
155
|
+
issue.request_response = self.get_io(xml)
|
|
156
|
+
return issue
|
|
157
|
+
|
|
158
|
+
def create_regscale_finding(self, issue: Issue, scan_time: datetime, fmt: str) -> Optional[IntegrationFinding]:
|
|
159
|
+
"""
|
|
160
|
+
Create a RegScale finding from a Burp Issue
|
|
161
|
+
|
|
162
|
+
:param Issue issue: Burp Issue
|
|
163
|
+
:param datetime scan_time: Scan time
|
|
164
|
+
:param str fmt: Format for datetime object
|
|
165
|
+
:return: RegScale Issue
|
|
166
|
+
:rtype: Optional[IntegrationFinding]
|
|
167
|
+
"""
|
|
168
|
+
remediation_actions = None
|
|
169
|
+
if issue.severity.lower() == "info":
|
|
170
|
+
return None
|
|
171
|
+
due_date = self.get_due_delta(issue.severity)
|
|
172
|
+
if issue.detail and issue.remediation_background:
|
|
173
|
+
remediation_actions = issue.detail + "<br>" + issue.remediation_background
|
|
174
|
+
elif issue.remediation_background:
|
|
175
|
+
remediation_actions = issue.remediation_background
|
|
176
|
+
elif issue.detail:
|
|
177
|
+
remediation_actions = issue.detail
|
|
178
|
+
# No CVE available, must use background
|
|
179
|
+
cve = self.extract_cve(issue.background)
|
|
180
|
+
external_id = str(hex(int(issue.type)) if issue.type and (issue.type).isdigit() else issue.type).replace(
|
|
181
|
+
"0x", "0x00"
|
|
182
|
+
) # Use burp hexidecimal issue type and format as external_id
|
|
183
|
+
finding = IntegrationFinding(
|
|
184
|
+
control_labels=[], # Add an empty list for control_labels
|
|
185
|
+
category="Burp Vulnerability", # Add a default category
|
|
186
|
+
title=issue.name,
|
|
187
|
+
description=(issue.background if issue.background else "")[:255],
|
|
188
|
+
severity=RegscaleIssue.assign_severity(issue.severity),
|
|
189
|
+
status="Open",
|
|
190
|
+
asset_identifier=issue.host,
|
|
191
|
+
external_id=external_id,
|
|
192
|
+
remediation=(remediation_actions if remediation_actions else "update affected package")[:255],
|
|
193
|
+
cvss_score=None,
|
|
194
|
+
cve=cve,
|
|
195
|
+
cvss_v3_base_score=None,
|
|
196
|
+
source_rule_id=str(issue.type),
|
|
197
|
+
vulnerability_type="Vulnerability Scan",
|
|
198
|
+
baseline="Burp Host",
|
|
199
|
+
recommendation_for_mitigation=issue.remediation_background,
|
|
200
|
+
results=issue.detail,
|
|
201
|
+
plugin_name=issue.type,
|
|
202
|
+
plugin_id=issue.type,
|
|
203
|
+
ip_address=issue.host,
|
|
204
|
+
)
|
|
205
|
+
if issue.detail:
|
|
206
|
+
finding.description = finding.description + "<br>" + issue.detail
|
|
207
|
+
if issue.cwes:
|
|
208
|
+
finding.description = finding.description + "<br>" + ", ".join(issue.cwes)
|
|
209
|
+
finding.first_seen = datetime.strftime(scan_time, fmt)
|
|
210
|
+
finding.last_seen = datetime.strftime(scan_time, fmt)
|
|
211
|
+
if scan_time + timedelta(days=due_date) < datetime.now():
|
|
212
|
+
finding.due_date = datetime.strftime(datetime.now() + timedelta(days=due_date), fmt)
|
|
213
|
+
else:
|
|
214
|
+
finding.due_date = datetime.strftime(scan_time + timedelta(days=due_date), fmt)
|
|
215
|
+
finding.basis_for_adjustment = "Burp Scan import"
|
|
216
|
+
|
|
217
|
+
return finding
|
|
218
|
+
|
|
219
|
+
def gen_findings(self, root: Element) -> None:
|
|
220
|
+
"""
|
|
221
|
+
Generate issues
|
|
222
|
+
|
|
223
|
+
:param Element root: Root
|
|
224
|
+
:rtype: None
|
|
225
|
+
"""
|
|
226
|
+
issues = []
|
|
227
|
+
findings = set()
|
|
228
|
+
self.existing_issues = RegscaleIssue.get_all_by_parent(parent_id=self.parent_id, parent_module="securityplans")
|
|
229
|
+
root_issues = root.findall("issue")
|
|
230
|
+
fmt = "%Y-%m-%d %H:%M:%S"
|
|
231
|
+
scan_time = datetime.strptime(root.attrib["exportTime"], "%a %b %d %H:%M:%S %Z %Y")
|
|
232
|
+
for xml in root_issues:
|
|
233
|
+
issue = self.create_issue(xml)
|
|
234
|
+
issues.append(issue)
|
|
235
|
+
regscale_finding = self.create_regscale_finding(issue, scan_time, fmt)
|
|
236
|
+
if regscale_finding and regscale_finding not in findings:
|
|
237
|
+
findings.add(regscale_finding)
|
|
238
|
+
self.num_findings += 1
|
|
239
|
+
self.burp_issues = issues
|
|
240
|
+
self.integration_findings = (x for x in findings)
|
|
241
|
+
|
|
242
|
+
def get_due_delta(self, severity: str) -> int:
|
|
243
|
+
"""
|
|
244
|
+
Find the due delta from the config file
|
|
245
|
+
|
|
246
|
+
:param str severity: The severity level
|
|
247
|
+
:return: Due date delta
|
|
248
|
+
:rtype: int
|
|
249
|
+
"""
|
|
250
|
+
# Leave at Tenable for now
|
|
251
|
+
due_delta = self.app.config["issues"]["tenable"]["low"]
|
|
252
|
+
if severity.lower() in ["medium", "moderate"]:
|
|
253
|
+
due_delta = self.app.config["issues"]["tenable"]["moderate"]
|
|
254
|
+
elif severity.lower() == "high":
|
|
255
|
+
due_delta = self.app.config["issues"]["tenable"]["high"]
|
|
256
|
+
elif severity.lower() == "critical":
|
|
257
|
+
due_delta = self.app.config["issues"]["tenable"]["critical"]
|
|
258
|
+
return due_delta
|
|
259
|
+
|
|
260
|
+
@classmethod
|
|
261
|
+
def get(cls, item: Any, key: Any) -> Optional[Any]:
|
|
262
|
+
"""
|
|
263
|
+
Get item
|
|
264
|
+
|
|
265
|
+
:param Any item: Object to try and get value from
|
|
266
|
+
:param Any key: The key to get the value with
|
|
267
|
+
:return: item stored at the provided key, or None if not found
|
|
268
|
+
:rtype: Optional[Any]
|
|
269
|
+
"""
|
|
270
|
+
try:
|
|
271
|
+
return item.find(key).text
|
|
272
|
+
except (AttributeError, KeyError):
|
|
273
|
+
return None
|
|
274
|
+
|
|
275
|
+
@staticmethod
|
|
276
|
+
def extract_numbers(string: str) -> List[int]:
|
|
277
|
+
"""
|
|
278
|
+
Extract numbers from string
|
|
279
|
+
|
|
280
|
+
:param str string: string with numbers
|
|
281
|
+
:return: List of numbers found in provided string
|
|
282
|
+
:rtype: List[int]
|
|
283
|
+
"""
|
|
284
|
+
return re.findall(r"\d+", string)
|
|
285
|
+
|
|
286
|
+
@staticmethod
|
|
287
|
+
def get_request_response(item: Element) -> RequestResponse:
|
|
288
|
+
"""
|
|
289
|
+
Get the Request/Response object
|
|
290
|
+
|
|
291
|
+
:param Element item: item
|
|
292
|
+
:return: The Request/Response object
|
|
293
|
+
:rtype: RequestResponse
|
|
294
|
+
"""
|
|
295
|
+
request_data = item.find(".//request")
|
|
296
|
+
if response_data := item.find(".//response"):
|
|
297
|
+
base64_dat = bool(request_data.attrib["base64"]) if "base64" in item.attrib else False
|
|
298
|
+
response_data_is_base64 = BurpResponse.is_base64(response_data.text)
|
|
299
|
+
method = request_data.attrib["method"] if "method" in item.attrib else "GET"
|
|
300
|
+
request = (
|
|
301
|
+
BurpRequest(dataString=request_data.text, base64=base64_dat, method=method)
|
|
302
|
+
if BurpRequest.is_base64(request_data.text)
|
|
303
|
+
else None
|
|
304
|
+
)
|
|
305
|
+
response = BurpResponse(
|
|
306
|
+
dataString=response_data.text if response_data_is_base64 else None,
|
|
307
|
+
base64=(bool(item.find(".//response").attrib["base64"]) if response_data_is_base64 else False),
|
|
308
|
+
)
|
|
309
|
+
return RequestResponse(request=request, response=response)
|
|
310
|
+
return RequestResponse(request=None, response=None)
|
|
311
|
+
|
|
312
|
+
def get_io(self, xml: Element) -> RequestResponse:
|
|
313
|
+
"""
|
|
314
|
+
Generate the Response Request object
|
|
315
|
+
|
|
316
|
+
:param Element xml: xml
|
|
317
|
+
:return: The Request/Response object
|
|
318
|
+
:rtype: RequestResponse
|
|
319
|
+
"""
|
|
320
|
+
for item in xml.findall("requestresponse"):
|
|
321
|
+
dat = item.find(".//request")
|
|
322
|
+
if dat.tag == "request":
|
|
323
|
+
return self.get_request_response(item)
|
|
324
|
+
|
|
325
|
+
def gen_assets(self) -> None:
|
|
326
|
+
"""
|
|
327
|
+
Generate RegScale Assets from Burp Issues
|
|
328
|
+
|
|
329
|
+
:rtype: None
|
|
330
|
+
:return: None
|
|
331
|
+
"""
|
|
332
|
+
assets: List[IntegrationAsset] = []
|
|
333
|
+
for issue in self.burp_issues:
|
|
334
|
+
host_name = None
|
|
335
|
+
hosts = self.extract_ip_address(issue.host)
|
|
336
|
+
host_name = issue.host
|
|
337
|
+
if hosts:
|
|
338
|
+
host_name = hosts[0]
|
|
339
|
+
integration_asset = IntegrationAsset(
|
|
340
|
+
name=host_name,
|
|
341
|
+
identifier=host_name,
|
|
342
|
+
asset_type="Virtual Machine (VM)",
|
|
343
|
+
asset_owner_id=self.app.config["userId"],
|
|
344
|
+
parent_id=self.parent_id,
|
|
345
|
+
parent_module=self.parent_module,
|
|
346
|
+
asset_category="Hardware",
|
|
347
|
+
date_last_updated=get_current_datetime(),
|
|
348
|
+
status="Active (On Network)",
|
|
349
|
+
ip_address=host_name if hosts else None,
|
|
350
|
+
is_public_facing=False,
|
|
351
|
+
mac_address="",
|
|
352
|
+
fqdn="",
|
|
353
|
+
disk_storage=0,
|
|
354
|
+
cpu=0,
|
|
355
|
+
ram=0,
|
|
356
|
+
)
|
|
357
|
+
if integration_asset.name not in [asset.name for asset in assets]:
|
|
358
|
+
assets.append(integration_asset)
|
|
359
|
+
self.num_assets += 1
|
|
360
|
+
self.integration_assets = (x for x in assets)
|
|
361
|
+
|
|
362
|
+
@staticmethod
|
|
363
|
+
def extract_ip_address(string: str) -> List[str]:
|
|
364
|
+
"""
|
|
365
|
+
Extract IP address from string
|
|
366
|
+
|
|
367
|
+
:param str string: string to extract IP address from
|
|
368
|
+
:return: List of IP addresses found in provided string
|
|
369
|
+
:rtype: List[str]
|
|
370
|
+
"""
|
|
371
|
+
ip_pattern = r"\b(?:\d{1,3}\.){3}\d{1,3}\b"
|
|
372
|
+
return re.findall(ip_pattern, string)
|
|
373
|
+
|
|
374
|
+
@staticmethod
|
|
375
|
+
def extract_links(html: str) -> List[str]:
|
|
376
|
+
"""
|
|
377
|
+
Extract links from html with standard library
|
|
378
|
+
|
|
379
|
+
:param str html: HTML
|
|
380
|
+
:return: List containing links found in the provided HTML string
|
|
381
|
+
:rtype: List[str]
|
|
382
|
+
"""
|
|
383
|
+
root = fromstring(html)
|
|
384
|
+
return [link.attrib["href"] for link in root.iter("a")]
|
|
385
|
+
|
|
386
|
+
@staticmethod
|
|
387
|
+
def extract_classifications(html: str) -> List[str]:
|
|
388
|
+
"""
|
|
389
|
+
Extract classifications from html with standard library
|
|
390
|
+
|
|
391
|
+
:param str html: HTML to parse classifications from
|
|
392
|
+
:return: List containing classifications found in the provided HTML string
|
|
393
|
+
:rtype: List[str]
|
|
394
|
+
"""
|
|
395
|
+
root = fromstring(html)
|
|
396
|
+
return [link.text.strip() for link in root.iter("a")]
|
|
397
|
+
|
|
398
|
+
def get_domain_name(self, url: str) -> str:
|
|
399
|
+
"""
|
|
400
|
+
Get the domain name from a URL
|
|
401
|
+
|
|
402
|
+
:param str url: URL
|
|
403
|
+
:return: Domain name
|
|
404
|
+
:rtype: str
|
|
405
|
+
"""
|
|
406
|
+
parsed_url = urlparse(url)
|
|
407
|
+
domain_name = parsed_url.hostname
|
|
408
|
+
return domain_name
|
|
409
|
+
|
|
410
|
+
def strip_html_tags(self, text: str) -> str:
|
|
411
|
+
"""
|
|
412
|
+
Strip HTML tags from a string.
|
|
413
|
+
|
|
414
|
+
:param str text: The string containing HTML tags
|
|
415
|
+
:return: The string without HTML tags
|
|
416
|
+
:rtype: str
|
|
417
|
+
"""
|
|
418
|
+
if not text:
|
|
419
|
+
return text
|
|
420
|
+
clean = re.sub(r"<.*?>", "", text)
|
|
421
|
+
return clean
|
|
422
|
+
|
|
423
|
+
def extract_cve(self, input_string: str) -> Optional[str]:
|
|
424
|
+
"""
|
|
425
|
+
Extract CVEs from a string.
|
|
426
|
+
|
|
427
|
+
:param str input_string: The string to extract CVEs from
|
|
428
|
+
:return: List of CVEs found in the provided string
|
|
429
|
+
:rtype: Optional[str]
|
|
430
|
+
"""
|
|
431
|
+
cve_pattern = r"CVE-\d{4}-\d{4,7}"
|
|
432
|
+
cve_ids = re.findall(cve_pattern, input_string)
|
|
433
|
+
return cve_ids.pop() if cve_ids else None
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Pydantic models for Burp Scans"""
|
|
4
|
+
|
|
5
|
+
# standard python imports
|
|
6
|
+
import base64
|
|
7
|
+
import json
|
|
8
|
+
from typing import List, Optional, Union, Any
|
|
9
|
+
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
|
|
12
|
+
from regscale.models.integration_models.base64 import Base64String
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class BurpResponse(BaseModel):
|
|
16
|
+
"""Response information"""
|
|
17
|
+
|
|
18
|
+
base64: Optional[bool] = None
|
|
19
|
+
dataString: Optional[Union[Base64String, str]] = None
|
|
20
|
+
|
|
21
|
+
def convert_to_response(self) -> Optional[str]:
|
|
22
|
+
"""
|
|
23
|
+
Convert base64 encoded response to a requests Response object
|
|
24
|
+
|
|
25
|
+
:return: Base64 decoded response as a string
|
|
26
|
+
:rtype: Optional[str]
|
|
27
|
+
"""
|
|
28
|
+
try:
|
|
29
|
+
bytes_data = base64.b64decode(self.dataString)
|
|
30
|
+
if bytes_data:
|
|
31
|
+
# Decode bytes to string
|
|
32
|
+
res = bytes_data.decode("utf-8")
|
|
33
|
+
except Exception:
|
|
34
|
+
res = None
|
|
35
|
+
return res
|
|
36
|
+
|
|
37
|
+
def convert_to_json(self) -> Optional[dict]:
|
|
38
|
+
"""
|
|
39
|
+
Convert base64 encoded response to a JSON object
|
|
40
|
+
|
|
41
|
+
:return: Base64 decoded response as a JSON object or None
|
|
42
|
+
:rtype: Optional[dict]
|
|
43
|
+
"""
|
|
44
|
+
res = self.convert_to_response()
|
|
45
|
+
data = None
|
|
46
|
+
if res:
|
|
47
|
+
# Find the start and end of the JSON data
|
|
48
|
+
start = res.find("{") # +1 to include the closing brace
|
|
49
|
+
|
|
50
|
+
# Extract the JSON data and convert it to a Python dictionary
|
|
51
|
+
try:
|
|
52
|
+
data = json.loads(res[start:])
|
|
53
|
+
except json.decoder.JSONDecodeError:
|
|
54
|
+
data = None
|
|
55
|
+
return data
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def is_base64(cls, sb: Any) -> bool:
|
|
59
|
+
"""
|
|
60
|
+
Check if string is base64 encoded
|
|
61
|
+
|
|
62
|
+
:param Any sb: String to check
|
|
63
|
+
:raises ValueError: If argument is not a string or bytes
|
|
64
|
+
:return: True if base64 encoded
|
|
65
|
+
:rtype: bool
|
|
66
|
+
"""
|
|
67
|
+
try:
|
|
68
|
+
if isinstance(sb, str):
|
|
69
|
+
# If there's any unicode here, an exception will be thrown and the function will return false
|
|
70
|
+
sb_bytes = bytes(sb, "ascii")
|
|
71
|
+
elif isinstance(sb, bytes):
|
|
72
|
+
sb_bytes = sb
|
|
73
|
+
else:
|
|
74
|
+
raise ValueError("Argument must be string or bytes")
|
|
75
|
+
# If this works, there's base64-encoded data here.
|
|
76
|
+
_ = base64.b64encode(base64.b64decode(sb_bytes)) == sb_bytes
|
|
77
|
+
except Exception:
|
|
78
|
+
return False
|
|
79
|
+
return True
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class Host(BaseModel):
|
|
83
|
+
"""Host information"""
|
|
84
|
+
|
|
85
|
+
ip: str
|
|
86
|
+
hostname: str
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class IssueDetailItem(BaseModel):
|
|
90
|
+
"""Issue Detail Item information"""
|
|
91
|
+
|
|
92
|
+
issueDetailItem: Optional[str] = None
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class BurpRequest(BurpResponse):
|
|
96
|
+
"""Request information"""
|
|
97
|
+
|
|
98
|
+
method: str
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class RequestResponse(BaseModel):
|
|
102
|
+
"""Request Response information"""
|
|
103
|
+
|
|
104
|
+
request: Optional[BurpRequest] = None
|
|
105
|
+
response: Optional[BurpResponse] = None
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class Issue(BaseModel):
|
|
109
|
+
"""Issue information"""
|
|
110
|
+
|
|
111
|
+
serialNumber: Optional[str] = None
|
|
112
|
+
type: Optional[str] = None
|
|
113
|
+
name: Optional[str] = None
|
|
114
|
+
host: Optional[Host] = None
|
|
115
|
+
path: Optional[str] = None
|
|
116
|
+
location: Optional[str] = None
|
|
117
|
+
severity: Optional[str] = None
|
|
118
|
+
confidence: Optional[str] = None
|
|
119
|
+
background: Optional[str] = None
|
|
120
|
+
remediation_background: Optional[str] = None
|
|
121
|
+
detail: Optional[str] = None
|
|
122
|
+
detail_items: Optional[List[IssueDetailItem]] = None
|
|
123
|
+
request_response: Optional[RequestResponse] = None
|
|
124
|
+
remediation_detail: Optional[str] = None
|
|
125
|
+
references: Optional[str] = None
|
|
126
|
+
vulnerability_classifications: Optional[str] = None
|
|
127
|
+
cwes: Optional[List[str]] = None
|
|
128
|
+
links: Optional[List[str]] = None
|