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,39 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Wiz Variables"""
|
|
4
|
+
|
|
5
|
+
from regscale.core.app.utils.variables import RsVariableType, RsVariablesMeta
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class WizVariables(metaclass=RsVariablesMeta):
|
|
9
|
+
"""
|
|
10
|
+
Wiz Variables class to define class-level attributes with type annotations and examples
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# Define class-level attributes with type annotations and examples
|
|
14
|
+
wizFullPullLimitHours: RsVariableType(int, 8) # type: ignore
|
|
15
|
+
wizUrl: RsVariableType(str, "https://api.us27.app.wiz.io/graphql", required=False) # type: ignore
|
|
16
|
+
wizIssueFilterBy: RsVariableType(
|
|
17
|
+
str,
|
|
18
|
+
'{"projectId": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"], "type": ["API_GATEWAY"]}',
|
|
19
|
+
default={},
|
|
20
|
+
required=False,
|
|
21
|
+
) # type: ignore
|
|
22
|
+
wizInventoryFilterBy: RsVariableType(
|
|
23
|
+
str,
|
|
24
|
+
'{"projectId": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"], "type": ["API_GATEWAY"]}',
|
|
25
|
+
default="""{"type":
|
|
26
|
+
[ "API_GATEWAY", "BACKUP_SERVICE", "CDN", "CICD_SERVICE", "CLOUD_LOG_CONFIGURATION",
|
|
27
|
+
"CLOUD_ORGANIZATION", "CONTAINER", "CONTAINER_IMAGE", "CONTAINER_REGISTRY", "CONTAINER_SERVICE",
|
|
28
|
+
"CONTROLLER_REVISION", "DATABASE", "DATA_WORKLOAD", "DB_SERVER", "DOMAIN", "EMAIL_SERVICE", "ENCRYPTION_KEY",
|
|
29
|
+
"FILE_SYSTEM_SERVICE", "FIREWALL", "GATEWAY", "KUBERNETES_CLUSTER", "LOAD_BALANCER",
|
|
30
|
+
"MANAGED_CERTIFICATE", "MESSAGING_SERVICE", "NAMESPACE", "NETWORK_INTERFACE", "PRIVATE_ENDPOINT",
|
|
31
|
+
"PRIVATE_LINK", "RAW_ACCESS_POLICY", "REGISTERED_DOMAIN", "RESOURCE_GROUP", "SECRET",
|
|
32
|
+
"SECRET_CONTAINER", "SERVERLESS", "SERVERLESS_PACKAGE", "SERVICE_ACCOUNT", "SERVICE_CONFIGURATION",
|
|
33
|
+
"STORAGE_ACCOUNT", "SUBNET", "SUBSCRIPTION", "VIRTUAL_DESKTOP", "VIRTUAL_MACHINE",
|
|
34
|
+
"VIRTUAL_MACHINE_IMAGE", "VIRTUAL_NETWORK", "VOLUME", "WEB_SERVICE" ] }""",
|
|
35
|
+
) # type: ignore
|
|
36
|
+
wizAccessToken: RsVariableType(str, "", sensitive=True, required=False) # type: ignore
|
|
37
|
+
wizClientId: RsVariableType(str, "", sensitive=True) # type: ignore
|
|
38
|
+
wizClientSecret: RsVariableType(str, "", sensitive=True) # type: ignore
|
|
39
|
+
wizLastInventoryPull: RsVariableType(str, "2022-01-01T00:00:00Z", required=False) # type: ignore
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""Wiz Authentication Module"""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
|
|
7
|
+
from regscale.core.app.api import Api
|
|
8
|
+
from regscale.core.app.logz import create_logger
|
|
9
|
+
from regscale.core.app.utils.app_utils import (
|
|
10
|
+
error_and_exit,
|
|
11
|
+
check_license,
|
|
12
|
+
)
|
|
13
|
+
from regscale.integrations.commercial.wizv2.variables import WizVariables
|
|
14
|
+
|
|
15
|
+
logger = create_logger()
|
|
16
|
+
AUTH0_URLS = [
|
|
17
|
+
"https://auth.wiz.io/oauth/token",
|
|
18
|
+
"https://auth0.gov.wiz.io/oauth/token",
|
|
19
|
+
"https://auth0.test.wiz.io/oauth/token",
|
|
20
|
+
"https://auth0.demo.wiz.io/oauth/token",
|
|
21
|
+
"https://auth.gov.wiz.io/oauth/token",
|
|
22
|
+
]
|
|
23
|
+
COGNITO_URLS = [
|
|
24
|
+
"https://auth.app.wiz.io/oauth/token",
|
|
25
|
+
"https://auth.test.wiz.io/oauth/token",
|
|
26
|
+
"https://auth.demo.wiz.io/oauth/token",
|
|
27
|
+
"https://auth.app.wiz.us/oauth/token",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def wiz_authenticate(client_id: Optional[str] = None, client_secret: Optional[str] = None) -> Optional[str]:
|
|
32
|
+
"""
|
|
33
|
+
Authenticate to Wiz
|
|
34
|
+
|
|
35
|
+
:param Optional[str] client_id: Wiz client ID, defaults to None
|
|
36
|
+
:param Optional[str] client_secret: Wiz client secret, defaults to None
|
|
37
|
+
:raises ValueError: No Wiz Client ID provided in system environment or CLI command
|
|
38
|
+
:return: token
|
|
39
|
+
:rtype: Optional[str]
|
|
40
|
+
"""
|
|
41
|
+
app = check_license()
|
|
42
|
+
api = Api()
|
|
43
|
+
# Login with service account to retrieve a 24hr access token that updates YAML file
|
|
44
|
+
logger.info("Authenticating - Loading configuration from init.yaml file")
|
|
45
|
+
|
|
46
|
+
# load the config from YAML
|
|
47
|
+
config = app.config
|
|
48
|
+
|
|
49
|
+
# get secrets
|
|
50
|
+
client_id = WizVariables.wizClientId if client_id is None else client_id
|
|
51
|
+
if not client_id:
|
|
52
|
+
raise ValueError("No Wiz Client ID provided in system environment or CLI command.")
|
|
53
|
+
client_secret = WizVariables.wizClientSecret if client_secret is None else client_secret
|
|
54
|
+
if not client_secret:
|
|
55
|
+
raise ValueError("No Wiz Client Secret provided in system environment or CLI command.")
|
|
56
|
+
wiz_auth_url = config.get("wizAuthUrl")
|
|
57
|
+
if not wiz_auth_url:
|
|
58
|
+
error_and_exit("No Wiz Authentication URL provided in the init.yaml file.")
|
|
59
|
+
|
|
60
|
+
# login and get token
|
|
61
|
+
logger.info("Attempting to retrieve OAuth token from Wiz.io.")
|
|
62
|
+
token, scope = get_token(
|
|
63
|
+
api=api,
|
|
64
|
+
client_id=client_id,
|
|
65
|
+
client_secret=client_secret,
|
|
66
|
+
token_url=wiz_auth_url,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# assign values
|
|
70
|
+
|
|
71
|
+
config["wizAccessToken"] = token
|
|
72
|
+
config["wizScope"] = scope
|
|
73
|
+
|
|
74
|
+
# write our the result to YAML
|
|
75
|
+
# write the changes back to file
|
|
76
|
+
app.save_config(config)
|
|
77
|
+
return token
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def get_token(api: Api, client_id: str, client_secret: str, token_url: str) -> tuple[str, str]:
|
|
81
|
+
"""
|
|
82
|
+
Return Wiz.io token
|
|
83
|
+
|
|
84
|
+
:param Api api: api instance
|
|
85
|
+
:param str client_id: Wiz client ID
|
|
86
|
+
:param str client_secret: Wiz client secret
|
|
87
|
+
:param str token_url: token url
|
|
88
|
+
:return: tuple of token and scope
|
|
89
|
+
:rtype: tuple[str, str]
|
|
90
|
+
"""
|
|
91
|
+
app = api.app
|
|
92
|
+
config = api.config
|
|
93
|
+
status_code = 500
|
|
94
|
+
logger.info("Getting a token")
|
|
95
|
+
response = api.post(
|
|
96
|
+
url=token_url,
|
|
97
|
+
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
|
98
|
+
json=None,
|
|
99
|
+
data=generate_authentication_params(client_id, client_secret, token_url),
|
|
100
|
+
)
|
|
101
|
+
if response.ok:
|
|
102
|
+
status_code = 200
|
|
103
|
+
logger.debug(response.reason)
|
|
104
|
+
# If response is unauthorized, try the first cognito url
|
|
105
|
+
if response.status_code == requests.codes.unauthorized:
|
|
106
|
+
try:
|
|
107
|
+
response = api.post(
|
|
108
|
+
url=COGNITO_URLS[0],
|
|
109
|
+
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
|
110
|
+
json=None,
|
|
111
|
+
data=generate_authentication_params(client_id, client_secret, COGNITO_URLS[0]),
|
|
112
|
+
)
|
|
113
|
+
if response.ok:
|
|
114
|
+
status_code = 200
|
|
115
|
+
logger.info(
|
|
116
|
+
"Successfully authenticated using the authorization url: %s, now updating init.yaml..",
|
|
117
|
+
COGNITO_URLS[0],
|
|
118
|
+
)
|
|
119
|
+
config["wizAuthUrl"] = COGNITO_URLS[0]
|
|
120
|
+
app.save_config(config)
|
|
121
|
+
except requests.RequestException:
|
|
122
|
+
error_and_exit(f"Wiz Authentication: {response.reason}")
|
|
123
|
+
if status_code != requests.codes.ok:
|
|
124
|
+
error_and_exit(f"Error authenticating to Wiz [{response.status_code}] - {response.text}")
|
|
125
|
+
response_json = response.json()
|
|
126
|
+
token = response_json.get("access_token")
|
|
127
|
+
scope = response_json.get("scope")
|
|
128
|
+
if not token:
|
|
129
|
+
error_and_exit(f'Could not retrieve token from Wiz: {response_json.get("message")}')
|
|
130
|
+
logger.info("SUCCESS: Wiz.io access token successfully retrieved.")
|
|
131
|
+
return token, scope
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def generate_authentication_params(client_id: str, client_secret: str, token_url: str) -> dict:
|
|
135
|
+
"""
|
|
136
|
+
Create the Correct Parameter format based on URL
|
|
137
|
+
|
|
138
|
+
:param str client_id: Wiz Client ID
|
|
139
|
+
:param str client_secret: Wiz Client Secret
|
|
140
|
+
:param str token_url: Wiz URL
|
|
141
|
+
:raises Exception: A generic exception if token_url provided is invalid
|
|
142
|
+
:return: Dictionary containing authentication parameters
|
|
143
|
+
:rtype: dict
|
|
144
|
+
"""
|
|
145
|
+
if token_url in AUTH0_URLS:
|
|
146
|
+
return {
|
|
147
|
+
"grant_type": "client_credentials",
|
|
148
|
+
"audience": "beyond-api",
|
|
149
|
+
"client_id": client_id,
|
|
150
|
+
"client_secret": client_secret,
|
|
151
|
+
}
|
|
152
|
+
if token_url in COGNITO_URLS:
|
|
153
|
+
return {
|
|
154
|
+
"grant_type": "client_credentials",
|
|
155
|
+
"audience": "wiz-api",
|
|
156
|
+
"client_id": client_id,
|
|
157
|
+
"client_secret": client_secret,
|
|
158
|
+
}
|
|
159
|
+
raise ValueError("Invalid Token URL")
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""xray RegScale integration"""
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from os import PathLike
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from regscale.models.integration_models.flat_file_importer import FlatFileImporter
|
|
12
|
+
from regscale.models.integration_models.xray import XRay
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@click.group()
|
|
16
|
+
def xray():
|
|
17
|
+
"""Performs actions on xray files."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@xray.command(name="import_xray")
|
|
21
|
+
@FlatFileImporter.common_scanner_options(
|
|
22
|
+
message="File path to the folder containing JFrog XRay .json files to process to RegScale.",
|
|
23
|
+
prompt="File path for JFrog XRay files",
|
|
24
|
+
import_name="xray",
|
|
25
|
+
)
|
|
26
|
+
def import_xray(
|
|
27
|
+
folder_path: PathLike[str],
|
|
28
|
+
regscale_ssp_id: int,
|
|
29
|
+
scan_date: datetime,
|
|
30
|
+
mappings_path: Path,
|
|
31
|
+
disable_mapping: bool,
|
|
32
|
+
s3_bucket: str,
|
|
33
|
+
s3_prefix: str,
|
|
34
|
+
aws_profile: str,
|
|
35
|
+
upload_file: bool,
|
|
36
|
+
) -> None:
|
|
37
|
+
"""
|
|
38
|
+
Import JFrog XRay scans, vulnerabilities and assets to RegScale from XRay .json files
|
|
39
|
+
"""
|
|
40
|
+
import_xray_files(
|
|
41
|
+
folder_path=folder_path,
|
|
42
|
+
regscale_ssp_id=regscale_ssp_id,
|
|
43
|
+
scan_date=scan_date,
|
|
44
|
+
mappings_path=mappings_path,
|
|
45
|
+
disable_mapping=disable_mapping,
|
|
46
|
+
s3_bucket=s3_bucket,
|
|
47
|
+
s3_prefix=s3_prefix,
|
|
48
|
+
aws_profile=aws_profile,
|
|
49
|
+
upload_file=upload_file,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def import_xray_files(
|
|
54
|
+
folder_path: PathLike[str],
|
|
55
|
+
regscale_ssp_id: int,
|
|
56
|
+
scan_date: datetime,
|
|
57
|
+
mappings_path: Path,
|
|
58
|
+
disable_mapping: bool,
|
|
59
|
+
s3_bucket: str,
|
|
60
|
+
s3_prefix: str,
|
|
61
|
+
aws_profile: str,
|
|
62
|
+
upload_file: Optional[bool] = True,
|
|
63
|
+
) -> None:
|
|
64
|
+
"""
|
|
65
|
+
Function to import XRay files to RegScale as assets and vulnerabilities
|
|
66
|
+
|
|
67
|
+
:param PathLike[str] folder_path: Path to the folder containing XRay files
|
|
68
|
+
:param int regscale_ssp_id: RegScale SSP ID
|
|
69
|
+
:param datetime scan_date: Scan date
|
|
70
|
+
:param Path mappings_path: Path to the header mapping file
|
|
71
|
+
:param bool disable_mapping: Disable mapping
|
|
72
|
+
:param str s3_bucket: S3 bucket to download the files from
|
|
73
|
+
:param str s3_prefix: S3 prefix to download the files from
|
|
74
|
+
:param str aws_profile: AWS profile to use for S3 access
|
|
75
|
+
:param Optional[bool] upload_file: Whether to upload the file to RegScale after processing, default: True
|
|
76
|
+
:rtype: None
|
|
77
|
+
"""
|
|
78
|
+
FlatFileImporter.import_files(
|
|
79
|
+
import_type=XRay,
|
|
80
|
+
import_name="XRay",
|
|
81
|
+
file_types=".json",
|
|
82
|
+
folder_path=folder_path,
|
|
83
|
+
regscale_ssp_id=regscale_ssp_id,
|
|
84
|
+
scan_date=scan_date,
|
|
85
|
+
mappings_path=mappings_path,
|
|
86
|
+
disable_mapping=disable_mapping,
|
|
87
|
+
s3_bucket=s3_bucket,
|
|
88
|
+
s3_prefix=s3_prefix,
|
|
89
|
+
aws_profile=aws_profile,
|
|
90
|
+
upload_file=upload_file,
|
|
91
|
+
)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from abc import abstractmethod
|
|
2
|
+
from regscale.core.app.application import Application
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Integration(Application):
|
|
6
|
+
"""
|
|
7
|
+
Base class for all integrations
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
def __init__(self, **kwargs):
|
|
11
|
+
super().__init__()
|
|
12
|
+
for key, value in kwargs.items():
|
|
13
|
+
setattr(self, key, value)
|
|
14
|
+
|
|
15
|
+
def __repr__(self):
|
|
16
|
+
return f"{self.__class__.__name__}"
|
|
17
|
+
|
|
18
|
+
def __str__(self):
|
|
19
|
+
return f"{self.__class__.__name__}"
|
|
20
|
+
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def authenticate(self, **kwargs):
|
|
23
|
+
"""
|
|
24
|
+
Authenticate to the integration
|
|
25
|
+
"""
|
|
26
|
+
pass
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Inventory(ABC):
|
|
5
|
+
def __init__(
|
|
6
|
+
self,
|
|
7
|
+
**kwargs,
|
|
8
|
+
):
|
|
9
|
+
for key, value in kwargs.items():
|
|
10
|
+
setattr(self, key, value)
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def pull(self):
|
|
14
|
+
"""
|
|
15
|
+
Pull inventory from an Integration platform into RegScale
|
|
16
|
+
"""
|
|
17
|
+
pass
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Integration issue module
|
|
5
|
+
"""
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
7
|
+
from datetime import time
|
|
8
|
+
from time import sleep
|
|
9
|
+
from typing import Callable, Dict, List, Set
|
|
10
|
+
|
|
11
|
+
from regscale.core.app.application import Application
|
|
12
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
13
|
+
from regscale.models import Issue, Vulnerability
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class IntegrationIssue(ABC):
|
|
17
|
+
"""
|
|
18
|
+
Integration issue class
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
# TOMOO This needs to be refactored to use ScannerIntegration.
|
|
22
|
+
# ScannerIntegration will have to be refactored to handle missing field mappings
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
**kwargs,
|
|
27
|
+
):
|
|
28
|
+
for key, value in kwargs.items():
|
|
29
|
+
setattr(self, key, value)
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def pull(self):
|
|
33
|
+
"""
|
|
34
|
+
Pull inventory from an Integration platform into RegScale
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def create_issues(
|
|
38
|
+
self,
|
|
39
|
+
issues: list[Issue],
|
|
40
|
+
):
|
|
41
|
+
"""
|
|
42
|
+
Create issues in RegScale
|
|
43
|
+
|
|
44
|
+
:param list[Issue] issues: list of issues to create
|
|
45
|
+
"""
|
|
46
|
+
Issue.batch_create(items=issues)
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
def create_or_update_issues(
|
|
50
|
+
issues: list[Issue],
|
|
51
|
+
parent_id: int,
|
|
52
|
+
parent_module: str,
|
|
53
|
+
):
|
|
54
|
+
"""
|
|
55
|
+
Create issues in RegScale
|
|
56
|
+
|
|
57
|
+
:param list[Issue] issues: list of issues to create or update
|
|
58
|
+
:param int parent_id: parent id
|
|
59
|
+
:param str parent_module: parent module
|
|
60
|
+
"""
|
|
61
|
+
existing_issues: List[Issue] = Issue.get_all_by_parent(parent_id=parent_id, parent_module=parent_module)
|
|
62
|
+
# otherIdentifier is the real key with coalfire/fedramp
|
|
63
|
+
insert_issues = [
|
|
64
|
+
item for item in issues if item.otherIdentifier not in {iss.otherIdentifier for iss in existing_issues}
|
|
65
|
+
]
|
|
66
|
+
update_issues: List[Issue] = []
|
|
67
|
+
for issue in issues:
|
|
68
|
+
if issue.otherIdentifier in {iss.otherIdentifier for iss in existing_issues}:
|
|
69
|
+
# get index of the issue
|
|
70
|
+
issue.id = [iss for iss in existing_issues if iss.otherIdentifier == issue.otherIdentifier].pop().id
|
|
71
|
+
# update the update_issues list
|
|
72
|
+
update_issues.append(issue)
|
|
73
|
+
if insert_issues:
|
|
74
|
+
Issue.batch_create(items=insert_issues)
|
|
75
|
+
if update_issues:
|
|
76
|
+
Issue.batch_update(items=list(update_issues))
|
|
77
|
+
|
|
78
|
+
@staticmethod
|
|
79
|
+
def close_issues(issue_vuln_map: Dict[int, Dict[int, List[Vulnerability]]]) -> None:
|
|
80
|
+
"""
|
|
81
|
+
Close issues in RegScale based on the newest vulnerabilities
|
|
82
|
+
|
|
83
|
+
:param Dict[int, Dict[int, List[Vulnerability]]] issue_vuln_map: map of issues to
|
|
84
|
+
vulnerabilities by way of assets!
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
update_issues: List[Issue] = []
|
|
88
|
+
for key in issue_vuln_map.keys():
|
|
89
|
+
# close existing_issues in RegScale if they are no longer relevant
|
|
90
|
+
for asset_key in issue_vuln_map[key].keys():
|
|
91
|
+
vulns = issue_vuln_map[key][asset_key]
|
|
92
|
+
if not [vuln for vuln in vulns if str(vuln.severity or "").lower() in ["moderate", "high", "critical"]]:
|
|
93
|
+
# Close issue
|
|
94
|
+
update_issue = Issue.get_object(object_id=key)
|
|
95
|
+
if update_issue:
|
|
96
|
+
update_issue.status = "Closed"
|
|
97
|
+
update_issue.dateCompleted = get_current_datetime()
|
|
98
|
+
update_issues.append(update_issue)
|
|
99
|
+
if update_issues:
|
|
100
|
+
Issue.batch_update(items=update_issues)
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A simple singleton class that loads custom integration mappings, if available
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from regscale.core.app.application import Application
|
|
6
|
+
|
|
7
|
+
# pylint: disable=C0415
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class IntegrationOverride:
|
|
11
|
+
"""
|
|
12
|
+
Custom Mapping class for findings
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from threading import Lock
|
|
16
|
+
from typing import Any, Optional
|
|
17
|
+
|
|
18
|
+
_instance = None
|
|
19
|
+
_lock = Lock() # Ensures thread safety for singleton instance creation
|
|
20
|
+
|
|
21
|
+
def __new__(cls, *args, **kwargs):
|
|
22
|
+
if not cls._instance:
|
|
23
|
+
with cls._lock:
|
|
24
|
+
if not cls._instance: # Double-checked locking
|
|
25
|
+
cls._instance = super(IntegrationOverride, cls).__new__(cls)
|
|
26
|
+
return cls._instance
|
|
27
|
+
|
|
28
|
+
def __init__(self, app):
|
|
29
|
+
from rich.console import Console
|
|
30
|
+
|
|
31
|
+
config = app.config
|
|
32
|
+
self.app = app
|
|
33
|
+
self.mapping = self._get_mapping(config)
|
|
34
|
+
if not hasattr(self, "_initialized"):
|
|
35
|
+
self.console = Console()
|
|
36
|
+
self._log_mappings()
|
|
37
|
+
self._initialized = True
|
|
38
|
+
|
|
39
|
+
def _log_mappings(self):
|
|
40
|
+
"""
|
|
41
|
+
Notify the user that overrides are found
|
|
42
|
+
"""
|
|
43
|
+
from rich.table import Table
|
|
44
|
+
|
|
45
|
+
table = Table(title="Custom Integration Mappings", show_header=True, header_style="bold magenta")
|
|
46
|
+
table.add_column("Integration", width=12, style="cyan")
|
|
47
|
+
table.add_column("Field", width=12, style="orange3") # Ensure this color is supported
|
|
48
|
+
table.add_column("Mapped Value", width=20, style="red")
|
|
49
|
+
|
|
50
|
+
for integration, fields in self.mapping.items():
|
|
51
|
+
for field, value in fields.items():
|
|
52
|
+
if value != "default":
|
|
53
|
+
table.add_row(integration, field, value)
|
|
54
|
+
|
|
55
|
+
if table.row_count > 0:
|
|
56
|
+
self.console.print(table)
|
|
57
|
+
|
|
58
|
+
def _get_mapping(self, config: dict) -> dict:
|
|
59
|
+
"""
|
|
60
|
+
Loads the mapping configuration from the application config.
|
|
61
|
+
|
|
62
|
+
:param dict config: The application configuration
|
|
63
|
+
:return: The mapping configuration
|
|
64
|
+
:rtype: dict
|
|
65
|
+
"""
|
|
66
|
+
return config.get("findingFromMapping", {})
|
|
67
|
+
|
|
68
|
+
def load(self, integration: Optional[str], field_name: Optional[str]) -> Optional[str]:
|
|
69
|
+
"""
|
|
70
|
+
Retrieves the mapped field name for a given integration and field name.
|
|
71
|
+
|
|
72
|
+
:param Optional[str] integration: The integration name
|
|
73
|
+
:param Optional[str] field_name: The field name
|
|
74
|
+
:return: The mapped field name
|
|
75
|
+
:rtype: Optional[str]
|
|
76
|
+
"""
|
|
77
|
+
if integration and self.mapping_exists(integration, field_name):
|
|
78
|
+
integration_map = self.mapping.get(integration.lower(), {})
|
|
79
|
+
return integration_map.get(field_name.lower())
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
def mapping_exists(self, integration: str, field_name: str) -> bool:
|
|
83
|
+
"""
|
|
84
|
+
Checks if a mapping exists for a given integration and field name.
|
|
85
|
+
|
|
86
|
+
:param str integration: The integration name
|
|
87
|
+
:param str field_name: The field name
|
|
88
|
+
:return: Whether the mapping exists
|
|
89
|
+
:rtype: bool
|
|
90
|
+
"""
|
|
91
|
+
the_map = self.mapping.get(integration.lower())
|
|
92
|
+
return the_map and field_name.lower() in the_map and the_map.get(field_name.lower()) != "default"
|
|
93
|
+
|
|
94
|
+
def field_map_validation(self, obj: Any, model_type: str) -> Optional[str]:
|
|
95
|
+
"""
|
|
96
|
+
Validate a field mapping between a RegScale object/dictionary and dataset.
|
|
97
|
+
|
|
98
|
+
:param Any obj: The object to validate
|
|
99
|
+
:param str model_type: The model type, ie. asset, issue, etc.
|
|
100
|
+
:return: The validated field
|
|
101
|
+
:rtype: Optional[str]
|
|
102
|
+
"""
|
|
103
|
+
match = None
|
|
104
|
+
try:
|
|
105
|
+
unique_override = self.app.config.get("uniqueOverride", {}).get(model_type, [])
|
|
106
|
+
if not unique_override:
|
|
107
|
+
return match
|
|
108
|
+
|
|
109
|
+
regscale_field = unique_override[0]
|
|
110
|
+
if not regscale_field:
|
|
111
|
+
return match
|
|
112
|
+
|
|
113
|
+
regscale_to_obj_mapping = {
|
|
114
|
+
# Tenable SC -> RegScale object -> RegScale field
|
|
115
|
+
"tenableasset": {
|
|
116
|
+
"asset": {
|
|
117
|
+
"ipAddress": "ip",
|
|
118
|
+
"name": "dnsName",
|
|
119
|
+
"dns": "dnsName",
|
|
120
|
+
"fqdn": "dnsName",
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
# dict key -> RegScale object -> RegScale field. This could grow to be quite large.
|
|
124
|
+
"dict": {
|
|
125
|
+
"asset": {
|
|
126
|
+
"ipAddress": "ipv4",
|
|
127
|
+
"name": "fqdn",
|
|
128
|
+
"dns": "fqdn",
|
|
129
|
+
"fqdn": "fqdn",
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
}
|
|
133
|
+
# The type an associated fields we are able to override. Limited for now.
|
|
134
|
+
supported_fields = {"asset": {"ipAddress", "name", "fqdn", "dns"}}
|
|
135
|
+
if regscale_field not in supported_fields.get(model_type.lower(), set()):
|
|
136
|
+
return match
|
|
137
|
+
|
|
138
|
+
model = obj.__class__.__name__.lower()
|
|
139
|
+
mapped_field = regscale_to_obj_mapping.get(model, {}).get(model_type, {}).get(regscale_field)
|
|
140
|
+
if not mapped_field:
|
|
141
|
+
return match
|
|
142
|
+
|
|
143
|
+
if isinstance(obj, dict):
|
|
144
|
+
match = obj.get(mapped_field)
|
|
145
|
+
elif hasattr(obj, mapped_field):
|
|
146
|
+
match = getattr(obj, mapped_field)
|
|
147
|
+
except (KeyError, AttributeError, IndexError, TypeError) as e:
|
|
148
|
+
self.app.logger.warning("Error parsing uniqueOverride: %s", str(e))
|
|
149
|
+
return match
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Public commands for the RegScale CLI
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
from regscale.core.lazy_group import LazyGroup
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.group(
|
|
10
|
+
cls=LazyGroup,
|
|
11
|
+
lazy_subcommands={
|
|
12
|
+
"import_docx": "regscale.integrations.public.fedramp.click.load_fedramp_docx",
|
|
13
|
+
"import_oscal": "regscale.integrations.public.fedramp.click.load_fedramp_oscal",
|
|
14
|
+
"import_ssp_xml": "regscale.integrations.public.fedramp.click.import_fedramp_ssp_xml",
|
|
15
|
+
"import_appendix_a": "regscale.integrations.public.fedramp.click.load_fedramp_appendix_a",
|
|
16
|
+
"import_inventory": "regscale.integrations.public.fedramp.click.import_fedramp_inventory",
|
|
17
|
+
"import_poam": "regscale.integrations.public.fedramp.click.import_fedramp_poam_template",
|
|
18
|
+
"import_drf": "regscale.integrations.public.fedramp.click.import_drf",
|
|
19
|
+
"import_cis_crm": "regscale.integrations.public.fedramp.click.import_ciscrm",
|
|
20
|
+
},
|
|
21
|
+
name="fedramp",
|
|
22
|
+
)
|
|
23
|
+
def fedramp():
|
|
24
|
+
"""Performs bulk processing of FedRAMP files (Upload trusted data only)."""
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@click.group(
|
|
29
|
+
cls=LazyGroup,
|
|
30
|
+
lazy_subcommands={
|
|
31
|
+
"ingest_pulses": "regscale.integrations.public.otx.ingest_pulses",
|
|
32
|
+
},
|
|
33
|
+
name="alienvault",
|
|
34
|
+
)
|
|
35
|
+
def alienvault():
|
|
36
|
+
"""AlienVault OTX Integration to load pulses to RegScale."""
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@click.group(
|
|
41
|
+
cls=LazyGroup,
|
|
42
|
+
lazy_subcommands={
|
|
43
|
+
"ingest_cisa_kev": "regscale.integrations.public.cisa.ingest_cisa_kev",
|
|
44
|
+
"ingest_cisa_alerts": "regscale.integrations.public.cisa.ingest_cisa_alerts",
|
|
45
|
+
},
|
|
46
|
+
name="cisa",
|
|
47
|
+
)
|
|
48
|
+
def cisa():
|
|
49
|
+
"""Performs administrative actions on the RegScale platform."""
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@click.group(
|
|
54
|
+
cls=LazyGroup,
|
|
55
|
+
lazy_subcommands={
|
|
56
|
+
"import": "regscale.integrations.public.criticality_updater.update_control_criticality",
|
|
57
|
+
},
|
|
58
|
+
name="criticality_updater",
|
|
59
|
+
)
|
|
60
|
+
def criticality_updater():
|
|
61
|
+
"""
|
|
62
|
+
Update the criticality of security controls in the catalog.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@click.group(
|
|
67
|
+
cls=LazyGroup,
|
|
68
|
+
lazy_subcommands={
|
|
69
|
+
"populate_controls": "regscale.integrations.public.emass.populate_workbook",
|
|
70
|
+
"import_slcm": "regscale.integrations.public.emass.import_slcm",
|
|
71
|
+
},
|
|
72
|
+
name="emass",
|
|
73
|
+
)
|
|
74
|
+
def emass():
|
|
75
|
+
"""Performs bulk processing of eMASS files (Upload trusted data only)."""
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@click.group(
|
|
80
|
+
cls=LazyGroup,
|
|
81
|
+
lazy_subcommands={
|
|
82
|
+
"sort_control_ids": "regscale.integrations.public.nist_catalog.sort_control_ids",
|
|
83
|
+
},
|
|
84
|
+
name="nist",
|
|
85
|
+
)
|
|
86
|
+
def nist():
|
|
87
|
+
"""Sort the controls of a catalog in RegScale."""
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@click.group(
|
|
92
|
+
cls=LazyGroup,
|
|
93
|
+
lazy_subcommands={
|
|
94
|
+
"version": "regscale.integrations.public.oscal.version",
|
|
95
|
+
"component": "regscale.integrations.public.oscal.upload_component",
|
|
96
|
+
"profile": "regscale.integrations.public.oscal.profile",
|
|
97
|
+
"catalog": "regscale.integrations.public.oscal.catalog",
|
|
98
|
+
},
|
|
99
|
+
name="oscal",
|
|
100
|
+
)
|
|
101
|
+
def oscal():
|
|
102
|
+
"""Performs bulk processing of OSCAL files."""
|
|
103
|
+
pass
|