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,467 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Command to bulk import scans by folder path."""
|
|
4
|
+
import csv
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
import logging
|
|
8
|
+
import os
|
|
9
|
+
import re
|
|
10
|
+
import shutil
|
|
11
|
+
import time
|
|
12
|
+
import xml.etree.ElementTree as ET
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from os import PathLike
|
|
15
|
+
from typing import Optional, Union
|
|
16
|
+
|
|
17
|
+
import click
|
|
18
|
+
import pandas as pd
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
from regscale.core.app.utils.file_utils import download_from_s3, get_files_by_folder
|
|
22
|
+
from regscale.models.integration_models.flat_file_importer import FlatFileImporter
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger("regscale")
|
|
25
|
+
|
|
26
|
+
FINGERPRINT_FILE_PATH = "regscale/integrations/commercial/import_all/scan_file_fingerprints.json"
|
|
27
|
+
EXCLUDE_MAPPING = ["burp", "nessus"] # Scan types that do not support custom mappings
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@click.group(name="import_all")
|
|
31
|
+
def import_all():
|
|
32
|
+
"""
|
|
33
|
+
Import scans, vulnerabilities and assets to RegScale from scan export files
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@import_all.command(name="run")
|
|
38
|
+
@FlatFileImporter.common_scanner_options(
|
|
39
|
+
message="Folder path containing scan files to process to RegScale.",
|
|
40
|
+
prompt="Folder path containing scan files",
|
|
41
|
+
import_name="all",
|
|
42
|
+
)
|
|
43
|
+
def import_all(
|
|
44
|
+
folder_path: PathLike[str],
|
|
45
|
+
regscale_ssp_id: int,
|
|
46
|
+
scan_date: datetime,
|
|
47
|
+
mappings_path: Path,
|
|
48
|
+
disable_mapping: bool,
|
|
49
|
+
s3_bucket: str,
|
|
50
|
+
s3_prefix: str,
|
|
51
|
+
aws_profile: str,
|
|
52
|
+
upload_file: bool,
|
|
53
|
+
):
|
|
54
|
+
"""
|
|
55
|
+
Import scans, vulnerabilities and assets to RegScale from scan export files
|
|
56
|
+
"""
|
|
57
|
+
if s3_bucket:
|
|
58
|
+
# Download files from S3 to folder_path
|
|
59
|
+
download_from_s3(s3_bucket, s3_prefix, folder_path, aws_profile)
|
|
60
|
+
|
|
61
|
+
import_all_scans(
|
|
62
|
+
folder_path=folder_path,
|
|
63
|
+
regscale_ssp_id=regscale_ssp_id,
|
|
64
|
+
scan_date=scan_date,
|
|
65
|
+
upload_file=upload_file,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def import_all_scans(
|
|
70
|
+
folder_path: PathLike[str],
|
|
71
|
+
regscale_ssp_id: int,
|
|
72
|
+
scan_date: datetime,
|
|
73
|
+
mappings_path: Optional[Path] = None,
|
|
74
|
+
disable_mapping: bool = False,
|
|
75
|
+
upload_file: Optional[bool] = True,
|
|
76
|
+
):
|
|
77
|
+
"""
|
|
78
|
+
Imports all scan files from a specified folder and processes them according to their scan type.
|
|
79
|
+
|
|
80
|
+
:param PathLike[str] folder_path: The path to the folder containing scan files.
|
|
81
|
+
:param int regscale_ssp_id: The RegScale SSP ID to associate with the scans.
|
|
82
|
+
:param datetime scan_date: The date of the scans.
|
|
83
|
+
:param Path mappings_path: The path to a custom mappings file.
|
|
84
|
+
:param bool disable_mapping: Flag to disable custom mapping prompts.
|
|
85
|
+
:param Optional[bool] upload_file: Whether to upload the file to RegScale after processing, defaults to True
|
|
86
|
+
"""
|
|
87
|
+
from regscale.integrations.commercial.aqua.aqua import import_aqua
|
|
88
|
+
from regscale.integrations.commercial.aws.cli import import_scans as import_aws
|
|
89
|
+
from regscale.integrations.commercial.burp import import_burp
|
|
90
|
+
from regscale.integrations.commercial.defender import import_alerts
|
|
91
|
+
from regscale.integrations.commercial.ecr import import_ecr
|
|
92
|
+
from regscale.integrations.commercial.grype import import_scans as import_grype_scans
|
|
93
|
+
from regscale.integrations.commercial.ibm import import_appscan
|
|
94
|
+
from regscale.integrations.commercial.nexpose import import_nexpose
|
|
95
|
+
from regscale.integrations.commercial.opentext.click import import_file as import_opentext_file
|
|
96
|
+
from regscale.integrations.commercial.prisma import import_prisma
|
|
97
|
+
from regscale.integrations.commercial.qualys import import_scans as import_qualys
|
|
98
|
+
from regscale.integrations.commercial.snyk import import_snyk
|
|
99
|
+
from regscale.integrations.commercial.tenablev2.click import import_nessus
|
|
100
|
+
from regscale.integrations.commercial.trivy import import_scans as import_trivy_scans
|
|
101
|
+
from regscale.integrations.commercial.veracode import import_veracode
|
|
102
|
+
from regscale.integrations.commercial.xray import import_xray
|
|
103
|
+
|
|
104
|
+
import_functions = {
|
|
105
|
+
"aqua": {"function": import_aqua, "custom_mapping": mappings_path},
|
|
106
|
+
"aws": {"function": import_aws, "custom_mapping": mappings_path},
|
|
107
|
+
"burp": {"function": import_burp, "custom_mapping": mappings_path},
|
|
108
|
+
"defender": {"function": import_alerts, "custom_mapping": mappings_path},
|
|
109
|
+
"ecr": {"function": import_ecr, "custom_mapping": mappings_path},
|
|
110
|
+
"grype": {"function": import_grype_scans, "custom_mapping": mappings_path},
|
|
111
|
+
"ibm": {"function": import_appscan, "custom_mapping": mappings_path},
|
|
112
|
+
"nessus": {"function": import_nessus, "custom_mapping": mappings_path},
|
|
113
|
+
"nexpose": {"function": import_nexpose, "custom_mapping": mappings_path},
|
|
114
|
+
"opentext": {"function": import_opentext_file, "custom_mapping": mappings_path},
|
|
115
|
+
"prisma": {"function": import_prisma, "custom_mapping": mappings_path},
|
|
116
|
+
"qualys": {"function": import_qualys, "custom_mapping": mappings_path},
|
|
117
|
+
"snyk": {"function": import_snyk, "custom_mapping": mappings_path},
|
|
118
|
+
"trivy": {"function": import_trivy_scans, "custom_mapping": mappings_path},
|
|
119
|
+
"veracode": {"function": import_veracode, "custom_mapping": mappings_path},
|
|
120
|
+
"xray": {"function": import_xray, "custom_mapping": mappings_path},
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
scans = set_scans(
|
|
124
|
+
get_files_by_folder(
|
|
125
|
+
str(folder_path),
|
|
126
|
+
exclude_non_scan_files=True,
|
|
127
|
+
file_excludes=[".DS_Store", "~", ".zip", "mapping.json", ".md", ".burp", ".html"],
|
|
128
|
+
directory_excludes=["processed"],
|
|
129
|
+
),
|
|
130
|
+
load_fingerprints(FINGERPRINT_FILE_PATH),
|
|
131
|
+
)
|
|
132
|
+
move_files(scans, str(folder_path))
|
|
133
|
+
|
|
134
|
+
scan_folders = {}
|
|
135
|
+
for scan_type in set(scans.values()):
|
|
136
|
+
scan_folder = os.path.join(folder_path, scan_type)
|
|
137
|
+
scan_folders[scan_type] = scan_folder
|
|
138
|
+
|
|
139
|
+
logger.debug(json.dumps(scan_folders, indent=2))
|
|
140
|
+
|
|
141
|
+
imports_to_process = {}
|
|
142
|
+
for scan_type, import_function in import_functions.items():
|
|
143
|
+
if scan_type in scan_folders:
|
|
144
|
+
imports_to_process[scan_type] = import_function
|
|
145
|
+
|
|
146
|
+
# Ask for any custom mappings
|
|
147
|
+
if input("Do you have any custom mapping files? (y/n): ").strip().lower() == "y" and not disable_mapping:
|
|
148
|
+
imports_to_process = set_custom_mappings(imports_to_process)
|
|
149
|
+
|
|
150
|
+
# Show user summary of what will be imported and ask for confirmation before starting imports
|
|
151
|
+
scan_counts = {scan_type: list(scans.values()).count(scan_type) for scan_type in set(scans.values())}
|
|
152
|
+
total_files = sum(scan_counts.values())
|
|
153
|
+
for scan_type, count in scan_counts.items():
|
|
154
|
+
print(f"{scan_type}: {count} files")
|
|
155
|
+
if input(f"Do you want to proceed with processing {total_files} scan file(s)? (y/n): ").strip().lower() != "y":
|
|
156
|
+
print("Aborting scan processing.")
|
|
157
|
+
else:
|
|
158
|
+
import_scans(imports_to_process, scan_folders, regscale_ssp_id, scan_date, upload_file)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def import_scans(
|
|
162
|
+
imports_to_process: dict, scan_folders: dict, regscale_ssp_id: int, scan_date: datetime, upload_file: bool
|
|
163
|
+
) -> None:
|
|
164
|
+
"""
|
|
165
|
+
Imports scans by invoking specified processing functions for each scan type.
|
|
166
|
+
:param dict imports_to_process: A dictionary where keys are scan types and values are dictionaries
|
|
167
|
+
containing the processing function and custom mapping path.
|
|
168
|
+
Example: {
|
|
169
|
+
"scan_type_1": {
|
|
170
|
+
"function": click_function_1,
|
|
171
|
+
"custom_mapping": "path/to/custom_mapping_1"
|
|
172
|
+
},
|
|
173
|
+
"scan_type_2": {
|
|
174
|
+
"function": click_function_2,
|
|
175
|
+
"custom_mapping": None
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
:param dict scan_folders: A dictionary where keys are scan types and values are folder paths
|
|
179
|
+
containing the scans for each type.
|
|
180
|
+
Example: {
|
|
181
|
+
"scan_type_1": "path/to/scan_folder_1",
|
|
182
|
+
"scan_type_2": "path/to/scan_folder_2"
|
|
183
|
+
}
|
|
184
|
+
:param int regscale_ssp_id: The RegScale SSP (System Security Plan) ID to associate with the scans.
|
|
185
|
+
:param datetime scan_date: The date of the scans in 'YYYY-MM-DD' format.
|
|
186
|
+
:param bool upload_file: Whether to upload the file to RegScale after processing
|
|
187
|
+
:rtype: None
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
ctx = click.get_current_context()
|
|
191
|
+
|
|
192
|
+
for scan_type, import_detail in imports_to_process.items():
|
|
193
|
+
kwargs = {"folder_path": scan_folders[scan_type]}
|
|
194
|
+
click_function = import_detail["function"]
|
|
195
|
+
kwargs["scan_date"] = scan_date
|
|
196
|
+
kwargs["regscale_ssp_id"] = regscale_ssp_id
|
|
197
|
+
# make sure upload_file and mappings_path are passed if the function requires them
|
|
198
|
+
for param in click_function.params:
|
|
199
|
+
if param.name == "mappings_path":
|
|
200
|
+
kwargs[param.name] = import_detail.get("custom_mapping") or Path.cwd() / "mappings" / scan_type
|
|
201
|
+
elif param.name == "upload_file":
|
|
202
|
+
kwargs[param.name] = upload_file
|
|
203
|
+
ctx.invoke(
|
|
204
|
+
click_function,
|
|
205
|
+
**kwargs,
|
|
206
|
+
)
|
|
207
|
+
logger.info("Waiting before processing the next scan...")
|
|
208
|
+
time.sleep(5)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def set_custom_mappings(imports_to_process: dict) -> dict:
|
|
212
|
+
"""
|
|
213
|
+
Prompts the user to provide custom mapping files for each scan type in the given imports.
|
|
214
|
+
:param dict imports_to_process: A dictionary where keys are scan types and values are dictionaries containing
|
|
215
|
+
the processing function and custom mapping path.
|
|
216
|
+
:return: The updated dictionary with custom mapping file paths added for each scan type, if provided by the user.
|
|
217
|
+
:rtype: dict
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
for scan_type, import_detail in imports_to_process.items():
|
|
221
|
+
if scan_type not in EXCLUDE_MAPPING:
|
|
222
|
+
if input(f"Do you have a custom mapping file for {scan_type}? (y/n): ").strip().lower() == "y":
|
|
223
|
+
import_detail["custom_mapping"] = input(f"Enter the mapping file path for {scan_type}: ").strip()
|
|
224
|
+
return imports_to_process
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def set_scans(file_list: list, fingerprints: dict) -> dict:
|
|
228
|
+
"""
|
|
229
|
+
Set scans for a list of files based on their fingerprints.
|
|
230
|
+
This function takes a list of file paths and a dictionary of fingerprints,
|
|
231
|
+
and returns a dictionary mapping each file path to its corresponding scan type.
|
|
232
|
+
If a file's fingerprint is not found in the provided fingerprints, it adds the
|
|
233
|
+
fingerprint and reloads the fingerprints from the fingerprint file path.
|
|
234
|
+
|
|
235
|
+
:param list file_list: A list of file paths to be scanned.
|
|
236
|
+
:param dict fingerprints: A dictionary where keys are file hashes and values are scan types.
|
|
237
|
+
:return: A dictionary mapping file paths to their corresponding scan types.
|
|
238
|
+
:rtype: dict
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
scans = {}
|
|
242
|
+
for file_path in file_list:
|
|
243
|
+
file_hash = get_fingerprint_hash(file_path)
|
|
244
|
+
scan_type = fingerprints.get(file_hash)
|
|
245
|
+
if scan_type is None or not scan_type:
|
|
246
|
+
add_fingerprint(file_hash, file_path)
|
|
247
|
+
fingerprints = load_fingerprints(FINGERPRINT_FILE_PATH)
|
|
248
|
+
scan_type = fingerprints.get(file_hash)
|
|
249
|
+
if scan_type:
|
|
250
|
+
scans[file_path] = scan_type
|
|
251
|
+
return scans
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def move_files(scans: dict, folder_path: str):
|
|
255
|
+
"""
|
|
256
|
+
Moves files to designated folders based on their scan type.
|
|
257
|
+
|
|
258
|
+
:param dict scans: A dictionary where keys are file paths and values are scan types.
|
|
259
|
+
:param str folder_path: The base folder path where files will be moved.
|
|
260
|
+
"""
|
|
261
|
+
|
|
262
|
+
for file_path, scan_type in scans.items():
|
|
263
|
+
scan_folder = os.path.join(folder_path, scan_type)
|
|
264
|
+
if not os.path.exists(scan_folder):
|
|
265
|
+
os.makedirs(scan_folder)
|
|
266
|
+
destination_path = os.path.join(scan_folder, os.path.basename(file_path))
|
|
267
|
+
shutil.move(file_path, destination_path)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def fingerprint_csv(file_path: str) -> str:
|
|
271
|
+
"""
|
|
272
|
+
Generates a SHA-256 fingerprint of the CSV file headers.
|
|
273
|
+
This function reads the headers of a CSV file, sorts them, and then
|
|
274
|
+
generates a SHA-256 hash of the concatenated header string.
|
|
275
|
+
|
|
276
|
+
:param str file_path: The path to the CSV file.
|
|
277
|
+
:return: The SHA-256 hash of the sorted CSV headers.
|
|
278
|
+
:rtype: str
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
with open(file_path, newline="") as csvfile:
|
|
282
|
+
reader = csv.reader(csvfile)
|
|
283
|
+
headers = next(reader)
|
|
284
|
+
headers_str = ",".join(sorted(headers))
|
|
285
|
+
return hashlib.sha256(headers_str.encode()).hexdigest()
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def fingerprint_json(file_path: str) -> str:
|
|
289
|
+
"""
|
|
290
|
+
Generates a SHA-256 fingerprint of the JSON file's keys.
|
|
291
|
+
This function reads a JSON file from the given file path, extracts the keys from the JSON data,
|
|
292
|
+
and generates a SHA-256 hash of the keys.
|
|
293
|
+
|
|
294
|
+
:param str file_path: The path to the JSON file.
|
|
295
|
+
:return: The SHA-256 hash of the JSON keys.
|
|
296
|
+
:rtype: str
|
|
297
|
+
"""
|
|
298
|
+
|
|
299
|
+
with open(file_path) as f:
|
|
300
|
+
keys = []
|
|
301
|
+
data = json.load(f)
|
|
302
|
+
if isinstance(data, list) and data:
|
|
303
|
+
keys = list_keys(data[0])
|
|
304
|
+
elif isinstance(data, dict):
|
|
305
|
+
keys = list_keys(data)
|
|
306
|
+
keys_str = str(keys)
|
|
307
|
+
return hashlib.sha256(keys_str.encode()).hexdigest()
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def list_keys(d: Union[dict, list], parent_key: Optional[str] = "") -> list:
|
|
311
|
+
"""
|
|
312
|
+
Recursively lists all keys in a nested dictionary or list structure.
|
|
313
|
+
|
|
314
|
+
:param Union[dict, list] d: The dictionary or list to traverse.
|
|
315
|
+
:param Optional[str] parent_key: The base key to prepend to each key.
|
|
316
|
+
:return: A list of keys (or indices) found in the nested structure.
|
|
317
|
+
:rtype: list
|
|
318
|
+
"""
|
|
319
|
+
|
|
320
|
+
keys = []
|
|
321
|
+
if isinstance(d, dict):
|
|
322
|
+
for k, v in d.items():
|
|
323
|
+
full_key = f"{parent_key}.{k}" if parent_key else k
|
|
324
|
+
if "findings[1]" in full_key:
|
|
325
|
+
break
|
|
326
|
+
keys.append(k)
|
|
327
|
+
keys.extend(list_keys(v, full_key))
|
|
328
|
+
elif isinstance(d, list):
|
|
329
|
+
for i, item in enumerate(d):
|
|
330
|
+
full_key = f"{parent_key}[{i}]"
|
|
331
|
+
if "findings[1]" in full_key:
|
|
332
|
+
break
|
|
333
|
+
keys.append(i)
|
|
334
|
+
keys.extend(list_keys(item, full_key))
|
|
335
|
+
return keys
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def fingerprint_xml(file_path: str) -> str:
|
|
339
|
+
"""
|
|
340
|
+
Generates a SHA-256 fingerprint for the root element of an XML file.
|
|
341
|
+
|
|
342
|
+
:param str file_path: The path to the XML file.
|
|
343
|
+
:return: The SHA-256 hash of the root element of the XML file.
|
|
344
|
+
:rtype: str
|
|
345
|
+
"""
|
|
346
|
+
pattern = r" at 0x[0-9a-fA-F]+"
|
|
347
|
+
tree = ET.parse(file_path)
|
|
348
|
+
root_element = re.sub(pattern, "", str(tree.getroot()))
|
|
349
|
+
return hashlib.sha256(root_element.encode()).hexdigest()
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def fingerprint_xlsx(file_path: str) -> str:
|
|
353
|
+
"""
|
|
354
|
+
Generates a SHA-256 fingerprint for the headers of an Excel file.
|
|
355
|
+
This function reads an Excel file from the given file path, extracts the headers,
|
|
356
|
+
sorts them, concatenates them into a single string, and then computes the SHA-256
|
|
357
|
+
hash of that string.
|
|
358
|
+
|
|
359
|
+
:param str file_path: The path to the Excel file.
|
|
360
|
+
:return: The SHA-256 hash of the sorted headers.
|
|
361
|
+
:rtype: str
|
|
362
|
+
"""
|
|
363
|
+
|
|
364
|
+
df = pd.read_excel(file_path)
|
|
365
|
+
headers = df.columns.tolist()
|
|
366
|
+
headers_str = ",".join(sorted(headers))
|
|
367
|
+
return hashlib.sha256(headers_str.encode()).hexdigest()
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def get_fingerprint_hash(file_path: str) -> str:
|
|
371
|
+
"""
|
|
372
|
+
Generate a fingerprint hash for a given file based on its extension.
|
|
373
|
+
Supported file extensions:
|
|
374
|
+
- .csv: Calls the fingerprint_csv function.
|
|
375
|
+
- .json: Calls the fingerprint_json function.
|
|
376
|
+
- .xml, .nessus: Calls the fingerprint_xml function.
|
|
377
|
+
- .xlsx: Calls the fingerprint_xlsx function.
|
|
378
|
+
|
|
379
|
+
:param str file_path: The path to the file for which the fingerprint hash is to be generated.
|
|
380
|
+
:return: The fingerprint hash of the file if the file extension is supported, otherwise None.
|
|
381
|
+
:rtype: str
|
|
382
|
+
"""
|
|
383
|
+
|
|
384
|
+
file_hash = None
|
|
385
|
+
if file_path.endswith(".csv"):
|
|
386
|
+
file_hash = fingerprint_csv(file_path)
|
|
387
|
+
elif file_path.endswith(".json"):
|
|
388
|
+
file_hash = fingerprint_json(file_path)
|
|
389
|
+
elif file_path.endswith(".xml") or file_path.endswith(".nessus"):
|
|
390
|
+
file_hash = fingerprint_xml(file_path)
|
|
391
|
+
elif file_path.endswith(".xlsx"):
|
|
392
|
+
file_hash = fingerprint_xlsx(file_path)
|
|
393
|
+
|
|
394
|
+
return file_hash or ""
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def add_fingerprint(file_hash: str, file_path: str) -> None:
|
|
398
|
+
"""
|
|
399
|
+
Adds a fingerprint entry for a given file hash and file path.
|
|
400
|
+
This function prompts the user to select a scan type from a list of supported scans
|
|
401
|
+
and associates the selected scan type with the provided file hash. The updated
|
|
402
|
+
fingerprints are then saved to the fingerprint file.
|
|
403
|
+
|
|
404
|
+
:param str file_hash: The hash of the file to add a fingerprint for.
|
|
405
|
+
:param str file_path: The path of the file to add a fingerprint for.
|
|
406
|
+
:rtype: None
|
|
407
|
+
"""
|
|
408
|
+
|
|
409
|
+
supported_scans = [
|
|
410
|
+
"SKIP FILE",
|
|
411
|
+
"aws",
|
|
412
|
+
"aqua",
|
|
413
|
+
"burp",
|
|
414
|
+
"defender",
|
|
415
|
+
"ecr",
|
|
416
|
+
"grype",
|
|
417
|
+
"ibm",
|
|
418
|
+
"nessus",
|
|
419
|
+
"nexpose",
|
|
420
|
+
"opentext",
|
|
421
|
+
"prisma",
|
|
422
|
+
"qualys",
|
|
423
|
+
"snyk",
|
|
424
|
+
"trivy",
|
|
425
|
+
"veracode",
|
|
426
|
+
"xray",
|
|
427
|
+
]
|
|
428
|
+
fingerprints = load_fingerprints(FINGERPRINT_FILE_PATH)
|
|
429
|
+
|
|
430
|
+
for i, scan in enumerate(supported_scans, 1):
|
|
431
|
+
print(f"{i}. {scan}")
|
|
432
|
+
choice = int(input(f"Enter the scan type number for file {file_path}: "))
|
|
433
|
+
if 2 <= choice <= len(supported_scans):
|
|
434
|
+
scan_type = supported_scans[choice - 1]
|
|
435
|
+
elif choice == 1:
|
|
436
|
+
print("Skipping file.")
|
|
437
|
+
return
|
|
438
|
+
else:
|
|
439
|
+
print("Invalid choice. Skipping file.")
|
|
440
|
+
return
|
|
441
|
+
fingerprints[file_hash] = scan_type
|
|
442
|
+
with open(FINGERPRINT_FILE_PATH, "w") as f:
|
|
443
|
+
json.dump(fingerprints, f, indent=2)
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def load_fingerprints(fingerprint_file_path: str) -> dict:
|
|
447
|
+
"""
|
|
448
|
+
Load fingerprints from a JSON file.
|
|
449
|
+
This function reads a JSON file containing fingerprints and returns them as a dictionary.
|
|
450
|
+
If the file does not exist, it will load the default fingerprints file from the RegScale CLI Package.
|
|
451
|
+
|
|
452
|
+
:param str fingerprint_file_path: The path to the JSON file containing fingerprints.
|
|
453
|
+
:return: A dictionary containing the fingerprints if the file exists, otherwise an empty dictionary.
|
|
454
|
+
:rtype: dict
|
|
455
|
+
"""
|
|
456
|
+
if os.path.exists(fingerprint_file_path):
|
|
457
|
+
with open(fingerprint_file_path, "r") as f:
|
|
458
|
+
fingerprints = json.load(f)
|
|
459
|
+
return fingerprints
|
|
460
|
+
else:
|
|
461
|
+
import importlib.resources as pkg_resources
|
|
462
|
+
|
|
463
|
+
with pkg_resources.open_text(
|
|
464
|
+
"regscale.integrations.commercial.import_all", "scan_file_fingerprints.json"
|
|
465
|
+
) as file:
|
|
466
|
+
fingerprints = json.load(file)
|
|
467
|
+
return fingerprints
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"3a425a4276c76a35e95864c08ff6d15689f6e05a4ae4fc45327d60411ea73cc7": "qualys",
|
|
3
|
+
"98abfaf1088f22e495bd6579445c465767f8d15af0c3e515db522c78428ea563": "prisma",
|
|
4
|
+
"604039b457dc467501f67e501652fb7cf401d42241bf516baf0635bf53bb21dd": "prisma",
|
|
5
|
+
"560883c9663477e21f0a9daf4335dc3506c60805ffb748270e8c36529b09a477": "prisma",
|
|
6
|
+
"993cefe39c7872b1b9475540a931e82d0acae26489194f29ec1075d18e63838a": "ecr",
|
|
7
|
+
"d4079c72eeaf2e41f47810e6f4580b5490f9a714f5cf7e0dbd43bb2da7289f0e": "ecr",
|
|
8
|
+
"4859fdd53830975f775c6218d516e53ab9929815408cefead39daa9e21ce01b5": "ecr",
|
|
9
|
+
"250ec705f509ba7c7062db771bd099005bbede1cb91a9f2726f829663ed04a7c": "snyk",
|
|
10
|
+
"264b5b1701c690e193c9ebbf7238f2f7e4724f519c53fd212f2b1c54d59cc1d0": "veracode",
|
|
11
|
+
"2f0149daff3d4bb7d869ee24336306c467399f66009149c2328b5e184dc86de1": "aqua",
|
|
12
|
+
"5a81c499e15786dbf364b1a80efe87204fadb30160ffdf16c99aa1115530e91c": "aqua",
|
|
13
|
+
"16e93222a3e5acf1c7f155bb4b1d2ca335abb6e92c2a8db3ba55212f05d32380": "nexpose",
|
|
14
|
+
"b963e090de916d23e8aa6010f792050b809194c141c3b4810cd8f118ce4c227e": "aws",
|
|
15
|
+
"4b9545c76a28c068f50e12c979c381a4bcd88a7ba1efb97be59406982e5597e9": "nessus",
|
|
16
|
+
"ee42d9946a756fa4d091f5fe988a0f3bfeb9ba0732dd631381e09f98d2be1ef6": "defender",
|
|
17
|
+
"8eb0b87f22e9a923315a450f123804553b3797ea2611b668d5fd996e827d5df2": "xray",
|
|
18
|
+
"72119792341edf640feb713a9bf8c2110268aae56cc5cb55a189941fdee66547": "prisma",
|
|
19
|
+
"3e9bd42202c49eee018dfdd250e88617329b0fdf2c919b4d4010e820d61571fc": "veracode",
|
|
20
|
+
"5d48ffb396e2e8a8a5a9811352a8c551c9f4315d631f248d078cf4e71a75f948": "ibm",
|
|
21
|
+
"51a83bea058347e4e13d26b7d61686bbef19c116f583bf3218eb60e40c813250": "prisma",
|
|
22
|
+
"b6c2b4a942f4c66c4f88f9934e7e39c7682504133055611fde6eb4f5e56ead68": "aws",
|
|
23
|
+
"a8b6803104eb886d7a9c8fec1e98ee185d1630222dd4f4fb93711010ad02a51a": "burp",
|
|
24
|
+
"b34ae012e05bb979e134bf88df53ff7e08955fc3d004612a4b0927f99b4652e6": "opentext",
|
|
25
|
+
"24574a348b59fac3dd7e1838f670cde43d6cf78f2d5f32d15ca2fec55e19bac7": "trivy",
|
|
26
|
+
"1361a3045ebf0c83eda2f96e25799139dbe7ed2ad7017daadee11eaefd75beac": "grype"
|
|
27
|
+
}
|