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,245 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Model for Custom Fields in the application"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Any, List, Optional
|
|
7
|
+
|
|
8
|
+
from pydantic import ConfigDict
|
|
9
|
+
|
|
10
|
+
from regscale.core.app.utils.app_utils import update_keys_to_lowercase_first_letter
|
|
11
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger("regscale")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CustomField(RegScaleModel):
|
|
17
|
+
_module_slug = "customFields"
|
|
18
|
+
|
|
19
|
+
id: Optional[int] = None
|
|
20
|
+
createdById: Optional[str] = None
|
|
21
|
+
dateCreated: Optional[str] = None
|
|
22
|
+
lastUpdatedById: Optional[str] = None
|
|
23
|
+
isPublic: Optional[bool] = None
|
|
24
|
+
moduleId: Optional[int] = None
|
|
25
|
+
fieldName: Optional[str] = None
|
|
26
|
+
fieldDataType: Optional[str] = None
|
|
27
|
+
active: Optional[bool] = None
|
|
28
|
+
fieldRequired: Optional[bool] = None
|
|
29
|
+
disabled: Optional[bool] = None
|
|
30
|
+
order: Optional[int] = None
|
|
31
|
+
tenantId: int = 1
|
|
32
|
+
dateLastUpdated: Optional[str] = None
|
|
33
|
+
data: Optional[List[Any]] = None
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
37
|
+
"""
|
|
38
|
+
Get additional endpoints for the CustomField model.
|
|
39
|
+
|
|
40
|
+
:return: A dictionary of additional endpoints
|
|
41
|
+
:rtype: ConfigDict
|
|
42
|
+
"""
|
|
43
|
+
return ConfigDict(
|
|
44
|
+
insert="/api/{model_slug}/1",
|
|
45
|
+
get_module_with_tenant="/api/{model_slug}/module/{tenantId}/{moduleId}",
|
|
46
|
+
get_module="/api/{model_slug}/module/{moduleId}",
|
|
47
|
+
get_module_required="/api/{model_slug}/moduleRequired/{moduleId}",
|
|
48
|
+
get_custom_field="/api/{model_slug}/{customFieldId}",
|
|
49
|
+
filter_custom_fields="/api/{model_slug}/{tenantId}/{moduleId}/{strSort}/{strDirection}/{intPage}/{intPageSize}",
|
|
50
|
+
update_batch_post="/api/{model_slug}/update/{tenantId}",
|
|
51
|
+
create_custom_field_post="/api/{model_slug}/{tenantId}",
|
|
52
|
+
update_custom_field_put="/api/{model_slug}/{tenantId}",
|
|
53
|
+
update_sort_order_post="/api/{model_slug}/sortOrder/{moduleId}",
|
|
54
|
+
enable_custom_field_put="/api/{model_slug}/enable/{tenantId}/{customFieldId}/{enabled}",
|
|
55
|
+
require_custom_field_put="/api/{model_slug}/require/{tenantId}/{customFieldId}/{required}",
|
|
56
|
+
get_by_parent="/api/{model_slug}/module/{strModule}",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
@classmethod
|
|
60
|
+
def get_list_by_module_id(cls, module_id: int) -> List["CustomField"]:
|
|
61
|
+
"""
|
|
62
|
+
Get a list of custom fields by module ID
|
|
63
|
+
|
|
64
|
+
:param int module_id: The ID of the module
|
|
65
|
+
:return: A list of custom fields
|
|
66
|
+
:rtype: List[CustomField]
|
|
67
|
+
"""
|
|
68
|
+
response = cls._get_api_handler().get(
|
|
69
|
+
endpoint=cls.get_endpoint("get_module").format(model_slug=cls._module_slug, moduleId=module_id)
|
|
70
|
+
)
|
|
71
|
+
custom_fields = []
|
|
72
|
+
if response and response.ok:
|
|
73
|
+
for custom_field in response.json():
|
|
74
|
+
custom_fields.append(CustomField(**custom_field))
|
|
75
|
+
return custom_fields
|
|
76
|
+
|
|
77
|
+
@classmethod
|
|
78
|
+
def get_custom_fields_by_module_id(cls, parent_module_id: int) -> List["CustomField"]:
|
|
79
|
+
"""
|
|
80
|
+
Get a list of custom fields by module ID
|
|
81
|
+
|
|
82
|
+
:param int parent_module_id: The ID of the module
|
|
83
|
+
:return: List of CustomField objects
|
|
84
|
+
:rtype: List[CustomField]
|
|
85
|
+
"""
|
|
86
|
+
custom_fields = CustomField.get_list_by_module_id(module_id=cls.get_module_id())
|
|
87
|
+
for field in custom_fields:
|
|
88
|
+
data_field_list = CustomFieldsData.get_list_by_parent_id_and_module_id(
|
|
89
|
+
parent_id=parent_module_id, module_id=field.moduleId
|
|
90
|
+
)
|
|
91
|
+
for data in data_field_list:
|
|
92
|
+
if data.fieldId == field.id:
|
|
93
|
+
field.data = data
|
|
94
|
+
if field.data:
|
|
95
|
+
field.data = update_keys_to_lowercase_first_letter(field.data)
|
|
96
|
+
return custom_fields
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class CustomFieldsData(RegScaleModel):
|
|
100
|
+
_module_slug = "customFieldsData"
|
|
101
|
+
id: Optional[int] = None
|
|
102
|
+
createdById: Optional[str] = None
|
|
103
|
+
dateCreated: Optional[str] = None
|
|
104
|
+
lastUpdatedById: Optional[str] = None
|
|
105
|
+
isPublic: Optional[bool] = None
|
|
106
|
+
moduleId: Optional[int] = None
|
|
107
|
+
parentId: Optional[int] = None
|
|
108
|
+
field: Optional[CustomField] = None
|
|
109
|
+
fieldId: Optional[int] = None
|
|
110
|
+
fieldName: Optional[str] = None
|
|
111
|
+
fieldValue: Optional[str] = None
|
|
112
|
+
fieldDataType: Optional[str] = None
|
|
113
|
+
fieldRequired: Optional[bool] = None
|
|
114
|
+
disabled: Optional[bool] = None
|
|
115
|
+
tenantsId: Optional[int] = None
|
|
116
|
+
dateLastUpdated: Optional[str] = None
|
|
117
|
+
|
|
118
|
+
@classmethod
|
|
119
|
+
def get_by_module_id(cls, parent_id: int, module_id: int) -> Optional[List["CustomFieldsData"]]:
|
|
120
|
+
"""
|
|
121
|
+
Get a list of custom fields by module ID.
|
|
122
|
+
|
|
123
|
+
:param int parent_id: The ID of the module parent id field
|
|
124
|
+
:param int module_id: The ID of the module
|
|
125
|
+
:return: A list of custom fields, None if no custom fields are found
|
|
126
|
+
:rtype: Optional[List[CustomFieldsData]]
|
|
127
|
+
"""
|
|
128
|
+
response = cls._get_api_handler().get(
|
|
129
|
+
endpoint=cls.get_endpoint("get_custom_fields_data_get").format(
|
|
130
|
+
model_slug=cls._module_slug, parentId=parent_id, moduleId=module_id
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
if response and response.ok:
|
|
134
|
+
return [CustomFieldsData(**data) for data in response.json()]
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
@classmethod
|
|
138
|
+
def get_by_id(cls, cid: int, module_id: int) -> Optional["CustomFieldsData"]:
|
|
139
|
+
"""
|
|
140
|
+
Get a list of custom fields by module ID.
|
|
141
|
+
|
|
142
|
+
:param int cid: The ID of the custom field
|
|
143
|
+
:param int module_id: The ID of the module
|
|
144
|
+
:return: A list of custom fields, None if no custom fields are found
|
|
145
|
+
:rtype: Optional[CustomFieldsData]
|
|
146
|
+
"""
|
|
147
|
+
response = cls._get_api_handler().get(
|
|
148
|
+
endpoint=cls.get_endpoint("get_custom_fields_data").format(
|
|
149
|
+
model_slug=cls._module_slug, id=cid, moduleId=module_id
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
if response and response.ok:
|
|
153
|
+
# print(response.json())
|
|
154
|
+
return CustomFieldsData(**response.json())
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
@staticmethod
|
|
158
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
159
|
+
"""
|
|
160
|
+
Get additional endpoints for the CustomFieldData model.
|
|
161
|
+
|
|
162
|
+
:return: A dictionary of additional endpoints
|
|
163
|
+
:rtype: ConfigDict
|
|
164
|
+
"""
|
|
165
|
+
return ConfigDict(
|
|
166
|
+
get_custom_fields_data="/api/{model_slug}/{id}/{moduleId}",
|
|
167
|
+
update_batch_post="/api/{model_slug}/update",
|
|
168
|
+
create_custom_field_data_post="/api/{model_slug}",
|
|
169
|
+
get_custom_fields_data_get="/api/{model_slug}/createCustomFieldsData/{parentId}/{moduleId}",
|
|
170
|
+
get_by_parent="/api/{model_slug}/{intParentID}/{strModule}",
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
@classmethod
|
|
174
|
+
def get_list_by_parent_id_and_module_id(cls, parent_id: int, module_id: int) -> List["CustomFieldsData"]:
|
|
175
|
+
"""
|
|
176
|
+
Get a list of custom fields by module ID.
|
|
177
|
+
|
|
178
|
+
:param int parent_id: The ID of the parent
|
|
179
|
+
:param int module_id: The ID of the module
|
|
180
|
+
:return: A list of custom field datas
|
|
181
|
+
:rtype: List["CustomFieldsData"]
|
|
182
|
+
"""
|
|
183
|
+
response = cls._get_api_handler().get(
|
|
184
|
+
endpoint=cls.get_endpoint("get_custom_fields_data_get").format(
|
|
185
|
+
model_slug=cls._module_slug, parentID=parent_id, moduleID=module_id
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
custom_fields = []
|
|
189
|
+
if response and response.ok:
|
|
190
|
+
for custom_field_data in response.json():
|
|
191
|
+
custom_fields.append(CustomFieldsData(**custom_field_data))
|
|
192
|
+
return custom_fields
|
|
193
|
+
|
|
194
|
+
@classmethod
|
|
195
|
+
def batch_update(cls, custom_data_fields: List["CustomFieldsData"]) -> bool:
|
|
196
|
+
"""
|
|
197
|
+
Batch update custom fields data.
|
|
198
|
+
|
|
199
|
+
:param List[CustomFieldsData] custom_data_fields: The list of custom fields data
|
|
200
|
+
:return: Whether the batch update was successful
|
|
201
|
+
:rtype: bool
|
|
202
|
+
"""
|
|
203
|
+
response = cls._get_api_handler().post(
|
|
204
|
+
endpoint=cls.get_endpoint("update_batch_post").format(model_slug=cls._module_slug),
|
|
205
|
+
data=[custom_data_field.dict() for custom_data_field in custom_data_fields],
|
|
206
|
+
)
|
|
207
|
+
if response and response.ok:
|
|
208
|
+
return True
|
|
209
|
+
else:
|
|
210
|
+
logger.error("Failed to batch update custom fields data")
|
|
211
|
+
return False
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class CustomFieldsSelectItem(RegScaleModel):
|
|
215
|
+
_module_slug = "customFieldsSelectItems"
|
|
216
|
+
|
|
217
|
+
@staticmethod
|
|
218
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
219
|
+
"""
|
|
220
|
+
Get additional endpoints for the CustomFieldSelectItem model.
|
|
221
|
+
|
|
222
|
+
:return: A dictionary of additional endpoints
|
|
223
|
+
:rtype: ConfigDict
|
|
224
|
+
"""
|
|
225
|
+
return ConfigDict(
|
|
226
|
+
create_items_post="/api/{model_slug}/items/{tenantId}",
|
|
227
|
+
update_items_put="/api/{model_slug}/items/{tenantId}",
|
|
228
|
+
get_items="/api/{model_slug}/items/{parentId}",
|
|
229
|
+
get_items_for_request="/api/{model_slug}/items/{parentId}/{moduleId}/{requestId}",
|
|
230
|
+
enable_item_put="/api/{model_slug}/enable/{tenantId}/{customFieldSelectItemId}/{enabled}",
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
id: Optional[int] = None
|
|
234
|
+
createdById: Optional[str] = None
|
|
235
|
+
dateCreated: Optional[str] = None
|
|
236
|
+
lastUpdatedById: Optional[str] = None
|
|
237
|
+
isPublic: Optional[bool] = None
|
|
238
|
+
moduleId: Optional[int] = None
|
|
239
|
+
parentId: Optional[int] = None
|
|
240
|
+
fieldKey: Optional[str] = None
|
|
241
|
+
fieldValue: Optional[str] = None
|
|
242
|
+
tenantsId: Optional[int] = None
|
|
243
|
+
dateLastUpdated: Optional[str] = None
|
|
244
|
+
disabled: Optional[bool] = None
|
|
245
|
+
itemOrder: Optional[int] = None
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Data model class"""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import List, Optional, cast
|
|
5
|
+
|
|
6
|
+
from pydantic import Field, ConfigDict
|
|
7
|
+
from requests import Response
|
|
8
|
+
|
|
9
|
+
from regscale.core.app.utils.app_utils import (
|
|
10
|
+
get_current_datetime,
|
|
11
|
+
create_progress_object,
|
|
12
|
+
)
|
|
13
|
+
from .regscale_model import RegScaleModel, T
|
|
14
|
+
from ...core.app.internal.model_editor import get_all_by_parent
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DataListItem(RegScaleModel):
|
|
18
|
+
"""
|
|
19
|
+
Data list item model class
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
id: int
|
|
23
|
+
dateCreated: str
|
|
24
|
+
dataType: str
|
|
25
|
+
dataSource: str
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class DataDataType(str, Enum):
|
|
29
|
+
"""
|
|
30
|
+
Data data type enum
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
JSON = "JSON"
|
|
34
|
+
XML = "XML"
|
|
35
|
+
YAML = "YAML"
|
|
36
|
+
|
|
37
|
+
def __str__(self):
|
|
38
|
+
return self.value
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class Data(RegScaleModel):
|
|
42
|
+
"""
|
|
43
|
+
Data model class
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
_module_slug = "data"
|
|
47
|
+
_unique_fields = [
|
|
48
|
+
["parentId", "parentModule", "dataSource", "dataType"],
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
id: Optional[int] = 0
|
|
52
|
+
createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
53
|
+
dateCreated: str = Field(default_factory=get_current_datetime)
|
|
54
|
+
lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
55
|
+
isPublic: bool = True
|
|
56
|
+
dataSource: str
|
|
57
|
+
dataType: Optional[str] = None
|
|
58
|
+
rawData: Optional[str] = None
|
|
59
|
+
parentId: int
|
|
60
|
+
parentModule: str
|
|
61
|
+
tenantsId: int = 1
|
|
62
|
+
dateLastUpdated: str = Field(default_factory=get_current_datetime)
|
|
63
|
+
|
|
64
|
+
@staticmethod
|
|
65
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
66
|
+
"""
|
|
67
|
+
Get additional endpoints for the Data model.
|
|
68
|
+
|
|
69
|
+
:return: A dictionary of additional endpoints
|
|
70
|
+
:rtype: ConfigDict
|
|
71
|
+
"""
|
|
72
|
+
return ConfigDict(
|
|
73
|
+
batch_create="/api/{model_slug}/batchCreate",
|
|
74
|
+
batch_update="/api/{model_slug}/batchUpdate",
|
|
75
|
+
get_all_by_parent="/api/{model_slug}/getAllByParent/{intParentID}/{strModule}",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def get_map(cls, plan_id: int, key_field: str = "parentId") -> dict[str, "Data"]:
|
|
80
|
+
"""
|
|
81
|
+
Get the asset map for the asset and cache it in Redis.
|
|
82
|
+
|
|
83
|
+
:param int plan_id: Security Plan ID
|
|
84
|
+
:param str key_field: Key field to use, defaults to "identifier"
|
|
85
|
+
:return: Data Map
|
|
86
|
+
:rtype: dict[str, "Data"]
|
|
87
|
+
|
|
88
|
+
# TODO: Implement filter by plan_id in RegScale API
|
|
89
|
+
"""
|
|
90
|
+
search_data = f"""query {{
|
|
91
|
+
data(skip: 0, take: 50) {{
|
|
92
|
+
items {{
|
|
93
|
+
{cls.build_graphql_fields()}
|
|
94
|
+
}}
|
|
95
|
+
totalCount
|
|
96
|
+
pageInfo {{
|
|
97
|
+
hasNextPage
|
|
98
|
+
}}
|
|
99
|
+
}}
|
|
100
|
+
}}"""
|
|
101
|
+
response = cls._get_api_handler().graph(query=search_data)
|
|
102
|
+
objects = cast(List["Data"], cls._handle_graph_response(response))
|
|
103
|
+
return_assets = {}
|
|
104
|
+
for obj in objects:
|
|
105
|
+
identifier = getattr(obj, key_field, None)
|
|
106
|
+
if identifier:
|
|
107
|
+
return_assets[identifier] = obj
|
|
108
|
+
|
|
109
|
+
return {k: v.model_dump_json() for k, v in return_assets.items()}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""DataCenter model for RegScale."""
|
|
2
|
+
|
|
3
|
+
import warnings
|
|
4
|
+
from urllib.parse import urljoin
|
|
5
|
+
|
|
6
|
+
from regscale.core.app.api import Api
|
|
7
|
+
from regscale.core.app.application import Application
|
|
8
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DataCenter(RegScaleModel):
|
|
12
|
+
"""DataCenter pydantic BaseModel."""
|
|
13
|
+
|
|
14
|
+
_module_slug = "datacenters"
|
|
15
|
+
|
|
16
|
+
id: int = 0
|
|
17
|
+
uuid: str = ""
|
|
18
|
+
facilityId: int
|
|
19
|
+
parentId: int
|
|
20
|
+
parentModule: str
|
|
21
|
+
isPublic: bool = True
|
|
22
|
+
facility: str = ""
|
|
23
|
+
|
|
24
|
+
def post(self, app: Application) -> dict:
|
|
25
|
+
"""
|
|
26
|
+
Post a DataCenter to RegScale
|
|
27
|
+
|
|
28
|
+
:param Application app: The application instance
|
|
29
|
+
:return: The response from the API
|
|
30
|
+
:rtype: dict
|
|
31
|
+
"""
|
|
32
|
+
warnings.warn(
|
|
33
|
+
"The 'post' method is deprecated, use 'create' method instead",
|
|
34
|
+
DeprecationWarning,
|
|
35
|
+
)
|
|
36
|
+
api = Api()
|
|
37
|
+
url = urljoin(app.config.get("domain", ""), "/api/datacenters")
|
|
38
|
+
data = self.dict()
|
|
39
|
+
response = api.post(url, json=data)
|
|
40
|
+
return response.json()
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import concurrent.futures
|
|
2
|
+
import logging
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import ConfigDict, Field
|
|
6
|
+
|
|
7
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
8
|
+
|
|
9
|
+
from .. import Property
|
|
10
|
+
from .regscale_model import RegScaleModel
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger("regscale")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Deviation(RegScaleModel):
|
|
16
|
+
"""
|
|
17
|
+
Deviation model class
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
_module_slug = "deviations"
|
|
21
|
+
_unique_fields = [
|
|
22
|
+
["parentIssueId", "deviationType", "rationale", "requestedImpactRating", "vulnerabilityId"],
|
|
23
|
+
]
|
|
24
|
+
_parent_id_field = "parentIssueId"
|
|
25
|
+
|
|
26
|
+
parentIssueId: int # Required
|
|
27
|
+
requestedImpactRating: str # Required
|
|
28
|
+
deviationType: str # Required
|
|
29
|
+
rationale: str # Required
|
|
30
|
+
|
|
31
|
+
id: int = 0
|
|
32
|
+
otherIdentifier: Optional[str] = None
|
|
33
|
+
isPublic: bool = True
|
|
34
|
+
uuid: Optional[str] = None
|
|
35
|
+
dateSubmitted: Optional[str] = None
|
|
36
|
+
evidenceDescription: Optional[str] = None
|
|
37
|
+
operationalImpacts: Optional[str] = None
|
|
38
|
+
riskJustification: Optional[str] = None
|
|
39
|
+
tmpExploitCodeMaturity: Optional[str] = None
|
|
40
|
+
tmpRemediationLevel: Optional[str] = None
|
|
41
|
+
tmpReportConfidence: Optional[str] = None
|
|
42
|
+
envConfidentiality: Optional[str] = None
|
|
43
|
+
envIntegrity: Optional[str] = None
|
|
44
|
+
envAvailability: Optional[str] = None
|
|
45
|
+
envAttackVector: Optional[str] = None
|
|
46
|
+
envAttackComplexity: Optional[str] = None
|
|
47
|
+
envPrivilegesRequired: Optional[str] = None
|
|
48
|
+
envUserInteraction: Optional[str] = None
|
|
49
|
+
envScope: Optional[str] = None
|
|
50
|
+
envModConfidentiality: Optional[str] = None
|
|
51
|
+
envModIntegrity: Optional[str] = None
|
|
52
|
+
envModAvailability: Optional[str] = None
|
|
53
|
+
vulnerabilityId: Optional[str] = None
|
|
54
|
+
baseScore: Optional[float] = None
|
|
55
|
+
temporalScore: Optional[float] = None
|
|
56
|
+
environmentalScore: Optional[float] = None
|
|
57
|
+
envAttackVectorExplanation: Optional[str] = None
|
|
58
|
+
envAttackComplexityExplanation: Optional[str] = None
|
|
59
|
+
envPrivilegesRequiredExplanation: Optional[str] = None
|
|
60
|
+
envUserInteractionExplanation: Optional[str] = None
|
|
61
|
+
envConfidentialityExplanation: Optional[str] = None
|
|
62
|
+
envIntegrityExplanation: Optional[str] = None
|
|
63
|
+
envAvailabilityExplanation: Optional[str] = None
|
|
64
|
+
tmpExploitCodeMaturityExplanation: Optional[str] = None
|
|
65
|
+
tmpRemediationLevelExplanation: Optional[str] = None
|
|
66
|
+
tmpReportConfidenceExplanation: Optional[str] = None
|
|
67
|
+
baseSeverity: Optional[str] = None
|
|
68
|
+
temporalSeverity: Optional[str] = None
|
|
69
|
+
environmentalSeverity: Optional[str] = None
|
|
70
|
+
finalVectorString: Optional[str] = None
|
|
71
|
+
overallRiskReductionExplanation: Optional[str] = None
|
|
72
|
+
additionalInformation: Optional[str] = None
|
|
73
|
+
drNumber: Optional[str] = None
|
|
74
|
+
createdById: str = Field(default_factory=RegScaleModel.get_user_id)
|
|
75
|
+
dateCreated: str = Field(default_factory=get_current_datetime)
|
|
76
|
+
lastUpdatedById: str = Field(default_factory=RegScaleModel.get_user_id)
|
|
77
|
+
dateLastUpdated: str = Field(default_factory=get_current_datetime)
|
|
78
|
+
|
|
79
|
+
@classmethod
|
|
80
|
+
def mapping(cls) -> dict:
|
|
81
|
+
"""
|
|
82
|
+
Get the mapping for the Deviation model.
|
|
83
|
+
|
|
84
|
+
:return: A dictionary of mappings
|
|
85
|
+
:rtype: dict
|
|
86
|
+
"""
|
|
87
|
+
return {
|
|
88
|
+
"FP": "False Positive (FP)",
|
|
89
|
+
"FP_RA": "False Positive (FP)",
|
|
90
|
+
"OR": "Operational Requirements (OR)",
|
|
91
|
+
"OR_RA": "RA & OR",
|
|
92
|
+
"OR RA": "RA & OR",
|
|
93
|
+
"RA": "Risk Adjustment (RA)",
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@staticmethod
|
|
97
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
98
|
+
"""
|
|
99
|
+
Get additional endpoints for the Deviations model.
|
|
100
|
+
|
|
101
|
+
:return: A dictionary of additional endpoints
|
|
102
|
+
:rtype: ConfigDict
|
|
103
|
+
"""
|
|
104
|
+
return ConfigDict( # type: ignore
|
|
105
|
+
get_by_issue="/api/{model_slug}/getbyIssue/{intParentID}/{includeDrNumber}",
|
|
106
|
+
get_all_by_security_plan="/api/{model_slug}/getAllBySecurityPlan/{sspId}/{includeDrNumber}",
|
|
107
|
+
export_deviation_by_ssp="/api/{model_slug}/getAllByPart/{intParentID}/{strModule}/{strType}/{strPart}",
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
@classmethod
|
|
111
|
+
def get_by_issue(cls, issue_id: int, include_dr_number: bool = True) -> Optional["Deviation"]:
|
|
112
|
+
"""
|
|
113
|
+
Get a deviation by issue id
|
|
114
|
+
|
|
115
|
+
:param int issue_id: Ths issue to search for
|
|
116
|
+
:param bool include_dr_number: Include DR number in the response
|
|
117
|
+
:return: A list of deviations
|
|
118
|
+
:rtype: Optional["Deviation"]
|
|
119
|
+
"""
|
|
120
|
+
response = cls._get_api_handler().get(
|
|
121
|
+
endpoint=cls.get_endpoint("get_by_issue").format(intParentID=issue_id, includeDrNumber=include_dr_number)
|
|
122
|
+
)
|
|
123
|
+
if response and response.status_code == 200:
|
|
124
|
+
return cls(**response.json())
|
|
125
|
+
return None
|
|
126
|
+
|
|
127
|
+
@classmethod
|
|
128
|
+
def get_by_security_plan(cls, ssp_id: int, include_dr_number: bool = True) -> List["Deviation"]:
|
|
129
|
+
"""
|
|
130
|
+
Get a list of deviations by ssp id
|
|
131
|
+
|
|
132
|
+
:param int ssp_id: Ths ssp to search for
|
|
133
|
+
:return: A list of deviations
|
|
134
|
+
:rtype: Optional["Deviation"]
|
|
135
|
+
"""
|
|
136
|
+
response = cls._get_api_handler().get(
|
|
137
|
+
endpoint=cls.get_endpoint("get_all_by_security_plan").format(
|
|
138
|
+
sspId=ssp_id, includeDrNumber=include_dr_number
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
if response and response.status_code == 200:
|
|
142
|
+
return [cls(**res) for res in response.json()]
|
|
143
|
+
return []
|
|
144
|
+
|
|
145
|
+
@classmethod
|
|
146
|
+
def get_dr_ids(cls, issue_id: int) -> Optional[Property]:
|
|
147
|
+
"""
|
|
148
|
+
Get a list of control implementations by plan ID.
|
|
149
|
+
|
|
150
|
+
:param int issue_id: Issue Id
|
|
151
|
+
:return: A single Property object with the DR number if it exists or None
|
|
152
|
+
:rtype: Optional[Property]
|
|
153
|
+
"""
|
|
154
|
+
properties = [
|
|
155
|
+
prop
|
|
156
|
+
for prop in Property.get_all_by_parent(parent_id=issue_id, parent_module="issues")
|
|
157
|
+
if prop.key == "dr_number"
|
|
158
|
+
]
|
|
159
|
+
if properties:
|
|
160
|
+
return properties.pop()
|
|
161
|
+
return None
|
|
162
|
+
|
|
163
|
+
@classmethod
|
|
164
|
+
def get_existing_deviations_by_ssp(
|
|
165
|
+
cls, ssp_id: int, issue_ids: List[int], poam_map: dict = None
|
|
166
|
+
) -> List["Deviation"]:
|
|
167
|
+
"""
|
|
168
|
+
Get existing deviations by SSP
|
|
169
|
+
|
|
170
|
+
:param int ssp_id: Security Plan ID
|
|
171
|
+
:param List[int] issue_ids: List of issue IDs
|
|
172
|
+
:param dict poam_map: POAM map, optional
|
|
173
|
+
:return: list of deviations
|
|
174
|
+
:rtype: List["Deviation"]
|
|
175
|
+
"""
|
|
176
|
+
# poam_map description:
|
|
177
|
+
# The main dict key of `id_other_identifier_map` are the `otherIdentifier` of each issue.
|
|
178
|
+
# The values of `id_other_identifier_map` are dictionaries themselves, with the following structure:
|
|
179
|
+
# The values are dictionaries with the following keys
|
|
180
|
+
# - `id`: The ID of the issue in RegScale
|
|
181
|
+
# - `dr_number`: The DR number of the issue
|
|
182
|
+
|
|
183
|
+
# CAUTION: This needs to be moved to platform specific code (see REG-9998)
|
|
184
|
+
logger.info("Looking up existing RegScale deviations for SSP# %i.. ", ssp_id)
|
|
185
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=50) as executor:
|
|
186
|
+
properties = (
|
|
187
|
+
[prop for prop in list(executor.map(cls.get_dr_ids, issue_ids)) if prop] if not poam_map else []
|
|
188
|
+
)
|
|
189
|
+
deviations = [dev for dev in list(executor.map(cls.get_by_issue, issue_ids)) if dev]
|
|
190
|
+
|
|
191
|
+
for deviation in deviations:
|
|
192
|
+
if not poam_map:
|
|
193
|
+
prop = [prop for prop in properties if prop.parentId == deviation.parentIssueId]
|
|
194
|
+
if prop:
|
|
195
|
+
deviation.extra_data = {"dr_number": prop.pop().value}
|
|
196
|
+
else:
|
|
197
|
+
deviation.extra_data = {"dr_number": None}
|
|
198
|
+
else:
|
|
199
|
+
match = [val for val in poam_map.values() if val.get("id") == deviation.parentIssueId]
|
|
200
|
+
if match:
|
|
201
|
+
deviation.extra_data = {"dr_number": match.pop().get("dr_number")}
|
|
202
|
+
|
|
203
|
+
return deviations
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Class for emails to send emails in RegScale platform"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from pydantic import ConfigDict, Field
|
|
8
|
+
|
|
9
|
+
from regscale.core.app.utils.app_utils import create_logger
|
|
10
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
11
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Email(RegScaleModel):
|
|
15
|
+
"""Class for email capabilities via RegScale platform"""
|
|
16
|
+
|
|
17
|
+
_module_slug = "email"
|
|
18
|
+
_exclude_graphql_fields = ["tenantsId"]
|
|
19
|
+
|
|
20
|
+
to: str
|
|
21
|
+
subject: str
|
|
22
|
+
id: Optional[int] = 0
|
|
23
|
+
fromEmail: str = Field(description="Cannot use from since it is a reserved word in Python", alias="from")
|
|
24
|
+
createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
25
|
+
dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
26
|
+
lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
27
|
+
isPublic: Optional[bool] = True
|
|
28
|
+
cc: Optional[str] = ""
|
|
29
|
+
body: Optional[str] = ""
|
|
30
|
+
dateSent: Optional[str] = Field(default_factory=get_current_datetime)
|
|
31
|
+
tenantsId: Optional[int] = 1
|
|
32
|
+
emailSenderId: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
33
|
+
dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
37
|
+
"""
|
|
38
|
+
Get additional endpoints for the Issues model.
|
|
39
|
+
|
|
40
|
+
:return: A dictionary of additional endpoints
|
|
41
|
+
:rtype: ConfigDict
|
|
42
|
+
"""
|
|
43
|
+
return ConfigDict(
|
|
44
|
+
get_domain="/api/{model_slug}/getDomain",
|
|
45
|
+
get_admin_email="/api/{model_slug}/getAdminEmail",
|
|
46
|
+
filter_my_email="/api/{model_slug}/filterMyEmail/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
|
|
47
|
+
filter_email="/api/{model_slug}/filterEmail/{strUser}/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
|
|
48
|
+
find_my_email="/api/{model_slug}/findMyEmail/{intID}",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def send(self) -> bool:
|
|
52
|
+
"""
|
|
53
|
+
Send the email
|
|
54
|
+
|
|
55
|
+
:return: Whether the email was sent successfully
|
|
56
|
+
:rtype: bool
|
|
57
|
+
"""
|
|
58
|
+
logger = create_logger()
|
|
59
|
+
endpoint = self.get_endpoint("insert")
|
|
60
|
+
response = self._get_api_handler().post(endpoint=endpoint, data=self.dict())
|
|
61
|
+
if response and response.ok:
|
|
62
|
+
return True
|
|
63
|
+
import json
|
|
64
|
+
|
|
65
|
+
logger.error(
|
|
66
|
+
f"Failed to create {self.__class__.__name__}\n Endpoint: {endpoint}\n Payload: "
|
|
67
|
+
f"{json.dumps(self.dict(), indent=2)}",
|
|
68
|
+
exc_info=True,
|
|
69
|
+
)
|
|
70
|
+
if response and not response.ok:
|
|
71
|
+
logger.error(f"Response Error: Code #{response.status_code}: {response.reason}\n{response.text}")
|
|
72
|
+
return False
|
|
73
|
+
if response is None:
|
|
74
|
+
error_msg = "Response was None"
|
|
75
|
+
logger.error(error_msg)
|
|
76
|
+
return False
|
|
77
|
+
error_msg = f"Response Code: {response.status_code}:{response.reason} - {response.text}"
|
|
78
|
+
logger.error(error_msg)
|
|
79
|
+
return False
|
|
80
|
+
|
|
81
|
+
def create(self, _=False) -> bool:
|
|
82
|
+
"""
|
|
83
|
+
Create the email
|
|
84
|
+
|
|
85
|
+
:return: Email object
|
|
86
|
+
:rtype: Email
|
|
87
|
+
"""
|
|
88
|
+
return self.send()
|
|
89
|
+
|
|
90
|
+
def delete(self) -> bool:
|
|
91
|
+
"""
|
|
92
|
+
Delete is not supported for emails, returns False
|
|
93
|
+
|
|
94
|
+
:return: False because it is not supported
|
|
95
|
+
:rtype: bool
|
|
96
|
+
"""
|
|
97
|
+
return False
|