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,50 @@
|
|
|
1
|
+
"""This module contains the Profile model."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import ConfigDict, Field
|
|
6
|
+
|
|
7
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
8
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Profile(RegScaleModel):
|
|
12
|
+
"""
|
|
13
|
+
Represents a security profile with various attributes.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
_module_slug = "profiles"
|
|
17
|
+
|
|
18
|
+
id: Optional[int] = None
|
|
19
|
+
category: Optional[str] = None
|
|
20
|
+
name: Optional[str]
|
|
21
|
+
createdById: str = Field(default_factory=RegScaleModel.get_user_id)
|
|
22
|
+
dateCreated: str = Field(default_factory=get_current_datetime)
|
|
23
|
+
lastUpdatedById: str = Field(default_factory=RegScaleModel.get_user_id)
|
|
24
|
+
dateLastUpdated: str = Field(default_factory=get_current_datetime)
|
|
25
|
+
profileOwnerId: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
26
|
+
tenantsId: Optional[int] = 1
|
|
27
|
+
uuid: Optional[str] = None
|
|
28
|
+
isPublic: Optional[bool] = True
|
|
29
|
+
availability: Optional[str] = None
|
|
30
|
+
confidentiality: Optional[str] = None
|
|
31
|
+
integrity: Optional[str] = None
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
35
|
+
"""
|
|
36
|
+
Get additional endpoints for the Profile model.
|
|
37
|
+
|
|
38
|
+
:return: A dictionary of additional endpoints
|
|
39
|
+
:rtype: ConfigDict
|
|
40
|
+
"""
|
|
41
|
+
return ConfigDict(
|
|
42
|
+
get_list="/api/{model_slug}/getList",
|
|
43
|
+
get_list_with_controls="/api/{model_slug}/getListWithControls",
|
|
44
|
+
get_count="/api/{model_slug}/getCount",
|
|
45
|
+
graph="/api/{model_slug}/graph",
|
|
46
|
+
apply_profile="/api/{model_slug}/applyProfile/{moduleId}/{moduleName}/{profileId}/{isPublic}",
|
|
47
|
+
filter_profiles="/api/{model_slug}/filterProfiles",
|
|
48
|
+
query_by_custom_field="/api/{model_slug}/queryByCustomField/{strFieldName}/{strValue}",
|
|
49
|
+
find_by_name="/api/{model_slug}/findByName/{strName}/{intID}",
|
|
50
|
+
)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Model for Profile Link in the application"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional, List
|
|
6
|
+
|
|
7
|
+
from pydantic import ConfigDict, Field
|
|
8
|
+
|
|
9
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
10
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ProfileLink(RegScaleModel):
|
|
14
|
+
"""
|
|
15
|
+
Profile Mapping Model
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
_module_slug = "profileLinks"
|
|
19
|
+
|
|
20
|
+
id: int
|
|
21
|
+
profileId: int
|
|
22
|
+
linkDate: Optional[str] = Field(default_factory=get_current_datetime)
|
|
23
|
+
parentId: int
|
|
24
|
+
parentModule: Optional[str] = None
|
|
25
|
+
tenantsId: Optional[int] = None
|
|
26
|
+
createdById: Optional[str] = None
|
|
27
|
+
dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
28
|
+
dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
29
|
+
isPublic: bool = False
|
|
30
|
+
lastUpdatedById: Optional[str] = None
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
34
|
+
"""
|
|
35
|
+
Get additional endpoints for the ProfileMapping model, using {model_slug} as a placeholder for the model slug.
|
|
36
|
+
|
|
37
|
+
:return: A dictionary of additional endpoints
|
|
38
|
+
:rtype: ConfigDict
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
return ConfigDict( # type: ignore
|
|
42
|
+
get_all_by_parent="/api/{model_slug}/getProfiles/{strModule}/{intParentID}",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def get_all_by_parent(cls, parent_id: int, parent_module: str) -> List["ProfileLink"]:
|
|
47
|
+
"""
|
|
48
|
+
Get a list of objects by parent.
|
|
49
|
+
# TODO: Update API to return needed data
|
|
50
|
+
|
|
51
|
+
:param int parent_id: The ID of the parent
|
|
52
|
+
:param str parent_module: The module of the parent
|
|
53
|
+
:return: A list of profile links
|
|
54
|
+
:rtype: List["ProfileLink]
|
|
55
|
+
"""
|
|
56
|
+
response = cls._get_api_handler().get(
|
|
57
|
+
endpoint=cls.get_endpoint("get_all_by_parent").format(
|
|
58
|
+
intParentID=parent_id,
|
|
59
|
+
strModule=parent_module,
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
records = []
|
|
63
|
+
for obj in response.json():
|
|
64
|
+
obj["parentModule"] = parent_module
|
|
65
|
+
obj["parentId"] = parent_id
|
|
66
|
+
obj["profileId"] = obj["profile"]["id"]
|
|
67
|
+
records.append(cls(**obj))
|
|
68
|
+
return records
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Model for Profile Mapping in the application"""
|
|
4
|
+
from typing import List, Optional
|
|
5
|
+
from urllib.parse import urljoin
|
|
6
|
+
|
|
7
|
+
from pydantic import ConfigDict, Field
|
|
8
|
+
|
|
9
|
+
from regscale.core.app.api import Api
|
|
10
|
+
from regscale.core.app.application import Application
|
|
11
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
12
|
+
from regscale.models.regscale_models.security_control import SecurityControl
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ProfileMapping(RegScaleModel):
|
|
16
|
+
"""
|
|
17
|
+
Profile Mapping Model
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
_module_slug = "profileMapping"
|
|
21
|
+
|
|
22
|
+
id: int = 0
|
|
23
|
+
profileID: int
|
|
24
|
+
controlID: int # the int id of the security control
|
|
25
|
+
controlId: Optional[str] = Field(alias="control_id", default=None) # the control id string i.e. AC-1
|
|
26
|
+
title: Optional[str] = None
|
|
27
|
+
family: Optional[str] = None
|
|
28
|
+
control: Optional[SecurityControl] = None
|
|
29
|
+
tenantsId: Optional[int] = None
|
|
30
|
+
createdById: Optional[str] = None
|
|
31
|
+
dateCreated: Optional[str] = None
|
|
32
|
+
dateLastUpdated: Optional[str] = None
|
|
33
|
+
isPublic: bool = True
|
|
34
|
+
lastUpdatedById: Optional[str] = None
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
38
|
+
"""
|
|
39
|
+
Get additional endpoints for the ProfileMapping model, using {model_slug} as a placeholder for the model slug.
|
|
40
|
+
|
|
41
|
+
:return: A dictionary of additional endpoints
|
|
42
|
+
:rtype: ConfigDict
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
return ConfigDict( # type: ignore
|
|
46
|
+
get_all_by_parent="/api/{model_slug}/getByProfile/{intParentID}",
|
|
47
|
+
lookup="/api/{model_slug}/lookup/{intProfileID}/{intControlID}",
|
|
48
|
+
get_by_profile="/api/{model_slug}/getByProfile/{intProfileID}",
|
|
49
|
+
oscal_prep="/api/{model_slug}/oscalPrep/{intProfileID}",
|
|
50
|
+
create_profile_mapping="/api/{model_slug}",
|
|
51
|
+
batch_create="/api/{model_slug}/batchCreate",
|
|
52
|
+
batch_delete="/api/{model_slug}/batchDelete",
|
|
53
|
+
delete_mapping="/api/{model_slug}/deleteMapping/{intProfileID}/{intControlID}",
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def get_by_profile(cls, profile_id: int) -> List["ProfileMapping"]:
|
|
58
|
+
"""
|
|
59
|
+
Get profile mappings by profile ID
|
|
60
|
+
|
|
61
|
+
:param int profile_id: Profile ID
|
|
62
|
+
:return: List of profile mappings
|
|
63
|
+
:rtype: List[ProfileMapping]
|
|
64
|
+
"""
|
|
65
|
+
response = cls._get_api_handler().get(
|
|
66
|
+
endpoint=cls.get_endpoint("get_by_profile").format(intProfileID=profile_id)
|
|
67
|
+
)
|
|
68
|
+
mappings = []
|
|
69
|
+
if response and response.ok:
|
|
70
|
+
mappings = [cls(**map) for map in response.json()]
|
|
71
|
+
for mapping in mappings:
|
|
72
|
+
if control := SecurityControl.get_object(object_id=mapping.controlID):
|
|
73
|
+
mapping.control = control
|
|
74
|
+
return mappings
|
|
75
|
+
|
|
76
|
+
def insert_profile_mapping(self, app: Application) -> dict:
|
|
77
|
+
"""
|
|
78
|
+
Insert a new profile mapping
|
|
79
|
+
|
|
80
|
+
:param Application app: Application
|
|
81
|
+
:raises Exception: API request failed
|
|
82
|
+
:return: dict of profile mapping
|
|
83
|
+
:rtype: dict
|
|
84
|
+
"""
|
|
85
|
+
api = Api()
|
|
86
|
+
# Convert the model to a dictionary
|
|
87
|
+
data = self.dict()
|
|
88
|
+
api_url = urljoin(app.config["domain"], "/api/profileMapping")
|
|
89
|
+
|
|
90
|
+
# Make the API call
|
|
91
|
+
response = api.post(url=api_url, json=data)
|
|
92
|
+
|
|
93
|
+
# Check the response
|
|
94
|
+
if not response.ok:
|
|
95
|
+
api.logger.debug(
|
|
96
|
+
f"API Call failed to: {api_url}\n{response.status_code}: {response.reason} {response.text}"
|
|
97
|
+
)
|
|
98
|
+
raise response.raise_for_status()
|
|
99
|
+
|
|
100
|
+
return response.json()
|
|
101
|
+
|
|
102
|
+
@staticmethod
|
|
103
|
+
def insert_batch(app: Application, mappings: List["ProfileMapping"]) -> list[dict]:
|
|
104
|
+
"""
|
|
105
|
+
Insert a new list of profile mappings as a batch
|
|
106
|
+
|
|
107
|
+
:param Application app: Application
|
|
108
|
+
:param List[ProfileMapping] mappings: List of profile mappings
|
|
109
|
+
:return: list[dict] of profile mappings
|
|
110
|
+
:rtype: list[dict]
|
|
111
|
+
"""
|
|
112
|
+
api = Api()
|
|
113
|
+
# Convert the model to a dictionary
|
|
114
|
+
|
|
115
|
+
data = [item.dict() for item in mappings]
|
|
116
|
+
for d in data:
|
|
117
|
+
d["isPublic"] = "true"
|
|
118
|
+
api_url = urljoin(app.config["domain"], "/api/profileMapping/batchCreate")
|
|
119
|
+
|
|
120
|
+
# Make the API call
|
|
121
|
+
response = api.post(url=api_url, json=data)
|
|
122
|
+
|
|
123
|
+
# Check the response
|
|
124
|
+
return response.json() if response.ok else response.raise_for_status()
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Model for a RegScale Link"""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import ConfigDict, Field
|
|
6
|
+
|
|
7
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
8
|
+
from .regscale_model import RegScaleModel
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Project(RegScaleModel):
|
|
12
|
+
_module_slug = "projects"
|
|
13
|
+
|
|
14
|
+
title: Optional[str] = "" # Required
|
|
15
|
+
phase: Optional[str] = "" # Required
|
|
16
|
+
projectManagerId: Optional[str] = Field(default_factory=RegScaleModel.get_user_id) # Required
|
|
17
|
+
id: Optional[int] = 0
|
|
18
|
+
uuid: Optional[str] = ""
|
|
19
|
+
otherID: Optional[str] = ""
|
|
20
|
+
description: Optional[str] = ""
|
|
21
|
+
benefits: Optional[str] = ""
|
|
22
|
+
startDate: Optional[str] = Field(default_factory=get_current_datetime)
|
|
23
|
+
endDate: Optional[str] = ""
|
|
24
|
+
actualFinish: Optional[str] = ""
|
|
25
|
+
percentComplete: Optional[int] = 0
|
|
26
|
+
budget: Optional[float] = 0.0
|
|
27
|
+
actualCosts: Optional[float] = 0.0
|
|
28
|
+
legislativeMandate: Optional[bool] = True
|
|
29
|
+
auditFinding: Optional[bool] = True
|
|
30
|
+
strategicPlan: Optional[bool] = True
|
|
31
|
+
costSavings: Optional[bool] = True
|
|
32
|
+
newRequirement: Optional[bool] = True
|
|
33
|
+
riskReduction: Optional[bool] = True
|
|
34
|
+
revenue: Optional[bool] = True
|
|
35
|
+
facilityId: Optional[int] = 0
|
|
36
|
+
orgId: Optional[int] = 0
|
|
37
|
+
parentId: Optional[int] = 0
|
|
38
|
+
parentModule: Optional[str] = ""
|
|
39
|
+
isPublic: Optional[bool] = True
|
|
40
|
+
|
|
41
|
+
@staticmethod
|
|
42
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
43
|
+
"""
|
|
44
|
+
Get additional endpoints for the Links model.
|
|
45
|
+
|
|
46
|
+
:return: A dictionary of additional endpoints
|
|
47
|
+
:rtype: ConfigDict
|
|
48
|
+
"""
|
|
49
|
+
return ConfigDict(
|
|
50
|
+
get_list="/api/{model_slug}/getList",
|
|
51
|
+
calendar_projects="/api/{model_slug}/calendarProjects/{dtDate}/{fId}/{orgId}/{userId}",
|
|
52
|
+
gantt_chart="/api/{model_slug}/ganttChart/{intId}",
|
|
53
|
+
status_board="/api/{model_slug}/statusboard/{strSearch}/{strPhase}/{strOwner}/{intPage}/{pageSize}",
|
|
54
|
+
graph="/api/{model_slug}/graph",
|
|
55
|
+
graph_by_date="/api/{model_slug}/graphByDate/{strGroupBy}/{year}",
|
|
56
|
+
filter_projects="/api/{model_slug}/filterProjects",
|
|
57
|
+
query_by_custom_field="/api/{model_slug}/queryByCustomField/{strFieldName}/{strValue}",
|
|
58
|
+
report="/api/{model_slug}/report/{strReport}",
|
|
59
|
+
schedule="/api/{model_slug}/schedule/{year}/{dvar}",
|
|
60
|
+
dashboard="/api/{model_slug}/dashboard/{strGroupBy}",
|
|
61
|
+
main_dashboard="/api/{model_slug}/mainDashboard/{intYear}",
|
|
62
|
+
main_dashboard_chart="/api/{model_slug}/mainDashboardChart/{year}",
|
|
63
|
+
)
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Create Properties model."""
|
|
4
|
+
import json
|
|
5
|
+
import logging
|
|
6
|
+
import math
|
|
7
|
+
from typing import Any, List, Optional, Union
|
|
8
|
+
|
|
9
|
+
from pydantic import ConfigDict, Field, field_validator
|
|
10
|
+
|
|
11
|
+
from regscale.core.app.api import Api
|
|
12
|
+
from regscale.core.app.application import Application
|
|
13
|
+
from regscale.core.app.internal.model_editor import get_all_by_parent
|
|
14
|
+
from regscale.core.app.utils.app_utils import get_current_datetime, recursive_items
|
|
15
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
16
|
+
from regscale.utils import flatten_dict
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger("regscale")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Property(RegScaleModel):
|
|
22
|
+
"""Properties plan model"""
|
|
23
|
+
|
|
24
|
+
_module_slug = "properties"
|
|
25
|
+
_unique_fields = [
|
|
26
|
+
["key", "parentId", "parentModule"],
|
|
27
|
+
]
|
|
28
|
+
_parent_id_field = "parentId"
|
|
29
|
+
|
|
30
|
+
id: int = 0
|
|
31
|
+
createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
32
|
+
dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
33
|
+
lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
34
|
+
isPublic: bool = True
|
|
35
|
+
key: Optional[str] = ""
|
|
36
|
+
value: Optional[Union[str, int, float]] = ""
|
|
37
|
+
label: Optional[str] = ""
|
|
38
|
+
otherAttributes: Optional[str] = ""
|
|
39
|
+
parentId: Optional[int] = 0
|
|
40
|
+
parentModule: Optional[str] = ""
|
|
41
|
+
dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
42
|
+
alt_id: Optional[str] = None
|
|
43
|
+
|
|
44
|
+
@field_validator("value", mode="before")
|
|
45
|
+
def validate_value(cls, value: Any) -> Any:
|
|
46
|
+
"""
|
|
47
|
+
Validate the value field and convert it to a string if it is a boolean or list
|
|
48
|
+
|
|
49
|
+
:param Any value: Value to validate
|
|
50
|
+
:return: Value if valid
|
|
51
|
+
:rtype: Any
|
|
52
|
+
"""
|
|
53
|
+
import math
|
|
54
|
+
|
|
55
|
+
if isinstance(value, bool):
|
|
56
|
+
return "True" if value else "False"
|
|
57
|
+
if isinstance(value, list):
|
|
58
|
+
return ", ".join(value)
|
|
59
|
+
if isinstance(value, float) and math.isnan(value):
|
|
60
|
+
return "NULL"
|
|
61
|
+
if isinstance(value, str) and value.strip() == "":
|
|
62
|
+
return "NULL"
|
|
63
|
+
if isinstance(value, dict):
|
|
64
|
+
return json.dumps(value)
|
|
65
|
+
return value or "NULL"
|
|
66
|
+
|
|
67
|
+
@staticmethod
|
|
68
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
69
|
+
"""
|
|
70
|
+
Get additional endpoints for the Properties model.
|
|
71
|
+
|
|
72
|
+
:return: A dictionary of additional endpoints
|
|
73
|
+
:rtype: ConfigDict
|
|
74
|
+
"""
|
|
75
|
+
return ConfigDict( # type: ignore
|
|
76
|
+
batch_create="/api/{model_slug}/batchCreate",
|
|
77
|
+
batch_update="/api/{model_slug}/batchUpdate",
|
|
78
|
+
get_all_by_parent="/api/{model_slug}/getAllByParent/{intParentID}/{strModule}",
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def create_properties_from_list(
|
|
83
|
+
parent_id: Union[str, int],
|
|
84
|
+
parent_module: str,
|
|
85
|
+
properties_list: List[dict],
|
|
86
|
+
) -> List["Property"]:
|
|
87
|
+
"""
|
|
88
|
+
Create a list of Properties objects from a list of dicts
|
|
89
|
+
|
|
90
|
+
:param Union[str, int] parent_id: ID of the SSP to create the Properties objects for
|
|
91
|
+
:param str parent_module: Parent module of the Properties objects
|
|
92
|
+
:param Union[str, int] properties_list: List of dicts to create objects from
|
|
93
|
+
:return: List[dict] of Properties objects
|
|
94
|
+
:rtype: List[Property]
|
|
95
|
+
"""
|
|
96
|
+
properties = [
|
|
97
|
+
Property(parentId=int(parent_id), parentModule=parent_module, **properties)
|
|
98
|
+
for properties in properties_list
|
|
99
|
+
]
|
|
100
|
+
return [property_.create_new_properties(return_object=True) for property_ in properties]
|
|
101
|
+
|
|
102
|
+
def create_new_properties(self, return_object: Optional[bool] = False) -> Union[bool, "Property"]:
|
|
103
|
+
"""
|
|
104
|
+
Create a new Properties object in RegScale
|
|
105
|
+
|
|
106
|
+
:param Optional[bool] return_object: Whether to return the object if successful
|
|
107
|
+
, defaults to False
|
|
108
|
+
:return: True or the Properties created if successful, False otherwise
|
|
109
|
+
:rtype: Union[bool, Property]
|
|
110
|
+
"""
|
|
111
|
+
api = Api()
|
|
112
|
+
data = self.dict()
|
|
113
|
+
data["id"] = None
|
|
114
|
+
data["createdById"] = api.config["userId"]
|
|
115
|
+
data["lastUpdatedById"] = api.config["userId"]
|
|
116
|
+
properties_response = api.post(
|
|
117
|
+
f'{api.config["domain"]}/api/properties/',
|
|
118
|
+
json=data,
|
|
119
|
+
)
|
|
120
|
+
if properties_response.ok:
|
|
121
|
+
logger.info("Created Properties: %s", properties_response.json()["id"])
|
|
122
|
+
if return_object:
|
|
123
|
+
return Property(**properties_response.json())
|
|
124
|
+
return True
|
|
125
|
+
logger.error("Error creating Properties: %s", properties_response.text)
|
|
126
|
+
return False
|
|
127
|
+
|
|
128
|
+
def __eq__(self, other: "Property") -> bool:
|
|
129
|
+
"""
|
|
130
|
+
Test equality of two Property objects
|
|
131
|
+
|
|
132
|
+
:param Property other: Other Property object to compare to
|
|
133
|
+
:return: Equality of two Property objects
|
|
134
|
+
:rtype: bool
|
|
135
|
+
"""
|
|
136
|
+
return (
|
|
137
|
+
self.key == other.key
|
|
138
|
+
and self.value == other.value
|
|
139
|
+
and self.parentId == other.parentId
|
|
140
|
+
and self.parentModule == other.parentModule
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
@staticmethod
|
|
144
|
+
def generate_property_list_from_dict(dat: dict) -> list["Property"]:
|
|
145
|
+
"""
|
|
146
|
+
Generate Property List from Dict
|
|
147
|
+
|
|
148
|
+
:param dict dat: Data to generate Property list from
|
|
149
|
+
:return: List of Properties
|
|
150
|
+
:rtype: list["Property"]
|
|
151
|
+
"""
|
|
152
|
+
kvs = recursive_items(dat)
|
|
153
|
+
return [Property(key=k, value=v, createdById="", parentModule="") for k, v in kvs]
|
|
154
|
+
|
|
155
|
+
@staticmethod
|
|
156
|
+
def update_properties(app: Application, prop_list: list["Property"]) -> None:
|
|
157
|
+
"""
|
|
158
|
+
Post a list of properties to RegScale
|
|
159
|
+
|
|
160
|
+
:param Application app: Application object
|
|
161
|
+
:param list[Property] prop_list: List of properties to post to RegScale
|
|
162
|
+
:rtype: None
|
|
163
|
+
"""
|
|
164
|
+
api = Api()
|
|
165
|
+
props = [prop.dict() for prop in prop_list]
|
|
166
|
+
res = api.put(
|
|
167
|
+
url=app.config["domain"] + "/api/properties/batchupdate",
|
|
168
|
+
json=props,
|
|
169
|
+
)
|
|
170
|
+
if res.status_code == 200:
|
|
171
|
+
if len(prop_list) > 0:
|
|
172
|
+
logger.info("Successfully updated %i properties to RegScale", len(prop_list))
|
|
173
|
+
else:
|
|
174
|
+
logger.error("Failed to update properties to RegScale\n%s", res.text)
|
|
175
|
+
|
|
176
|
+
@staticmethod
|
|
177
|
+
def existing_properties(app: Application, existing_assets: list[dict]) -> list["Property"]:
|
|
178
|
+
"""
|
|
179
|
+
Return a list of existing properties in RegScale
|
|
180
|
+
|
|
181
|
+
:param Application app: Application object
|
|
182
|
+
:param list[dict] existing_assets: List of assets from RegScale
|
|
183
|
+
:return: List of properties for the provided assets
|
|
184
|
+
:rtype: list["Property"]
|
|
185
|
+
"""
|
|
186
|
+
properties = []
|
|
187
|
+
api = Api()
|
|
188
|
+
for asset in existing_assets:
|
|
189
|
+
res = api.get(url=app.config["domain"] + f"/api/properties/getAllByParent/{asset['id']}/assets")
|
|
190
|
+
if res.status_code == 200:
|
|
191
|
+
for prop in res.json():
|
|
192
|
+
prop["alt_id"] = asset["wizId"]
|
|
193
|
+
properties.append(Property(**prop))
|
|
194
|
+
return properties
|
|
195
|
+
|
|
196
|
+
@staticmethod
|
|
197
|
+
def insert_properties(app: Application, prop_list: list["Property"]) -> list["Property"]:
|
|
198
|
+
"""
|
|
199
|
+
Post a list of properties to RegScale
|
|
200
|
+
|
|
201
|
+
:param Application app: Application instance
|
|
202
|
+
:param list[Property] prop_list: List of properties to post
|
|
203
|
+
:return: List of created properties in RegScale
|
|
204
|
+
:rtype: list["Property"]
|
|
205
|
+
"""
|
|
206
|
+
properties = []
|
|
207
|
+
api = Api()
|
|
208
|
+
res = api.post(
|
|
209
|
+
url=app.config["domain"] + "/api/properties/batchcreate",
|
|
210
|
+
json=[prop.dict() for prop in prop_list],
|
|
211
|
+
)
|
|
212
|
+
if res.status_code == 200:
|
|
213
|
+
if len(prop_list) > 0:
|
|
214
|
+
api.logger.info("Successfully posted %i properties to RegScale", len(prop_list))
|
|
215
|
+
properties = [Property(**prop) for prop in res.json()]
|
|
216
|
+
else:
|
|
217
|
+
logger.error("Failed to post properties to RegScale\n%s", res.text)
|
|
218
|
+
return properties
|
|
219
|
+
|
|
220
|
+
@staticmethod
|
|
221
|
+
def get_properties(wiz_data: str, wiz_id: str) -> List["Property"]:
|
|
222
|
+
"""
|
|
223
|
+
Convert Wiz properties data into a list of Property objects.
|
|
224
|
+
|
|
225
|
+
:param str wiz_data: JSON string containing Wiz information
|
|
226
|
+
:param str wiz_id: Identifier for a Wiz issue
|
|
227
|
+
:return: A list of Property objects derived from Wiz data
|
|
228
|
+
:rtype: List[Property]
|
|
229
|
+
"""
|
|
230
|
+
app = Application()
|
|
231
|
+
wiz_dict = json.loads(wiz_data)
|
|
232
|
+
flattened = flatten_dict(wiz_dict)
|
|
233
|
+
properties = []
|
|
234
|
+
|
|
235
|
+
current_datetime = get_current_datetime()
|
|
236
|
+
user_id = app.config["userId"]
|
|
237
|
+
|
|
238
|
+
for key, value in flattened:
|
|
239
|
+
# Skip empty values or empty dictionaries converted to strings
|
|
240
|
+
if not value or value == "{}":
|
|
241
|
+
continue
|
|
242
|
+
value = _value_checks(value)
|
|
243
|
+
# Create and add Property object if there's a meaningful value
|
|
244
|
+
if value:
|
|
245
|
+
prop = Property(
|
|
246
|
+
createdById=user_id,
|
|
247
|
+
dateCreated=current_datetime,
|
|
248
|
+
lastUpdatedById=user_id,
|
|
249
|
+
isPublic=True,
|
|
250
|
+
alt_id=wiz_id,
|
|
251
|
+
key=key,
|
|
252
|
+
value=value,
|
|
253
|
+
parentId=0,
|
|
254
|
+
parentModule="assets",
|
|
255
|
+
dateLastUpdated=current_datetime,
|
|
256
|
+
)
|
|
257
|
+
properties.append(prop)
|
|
258
|
+
|
|
259
|
+
return properties
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def _value_checks(value: Any) -> Any:
|
|
263
|
+
"""
|
|
264
|
+
Check if the value is a boolean or list and convert it to a string if needed
|
|
265
|
+
:param Any value: Value to check
|
|
266
|
+
:return: Converted value
|
|
267
|
+
:rtype: Any
|
|
268
|
+
"""
|
|
269
|
+
# Simplify handling of list and dict values
|
|
270
|
+
if isinstance(value, list):
|
|
271
|
+
value = value[0] if value else None # Get first item of the list if not empty
|
|
272
|
+
if isinstance(value, dict):
|
|
273
|
+
value = next((v for _, v in flatten_dict(value)), None)
|
|
274
|
+
|
|
275
|
+
# Replace NaN values with an empty string
|
|
276
|
+
if isinstance(value, (int, float)) and math.isnan(value):
|
|
277
|
+
value = ""
|
|
278
|
+
return value
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module contains the Questions model for RegScale.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from typing import Optional, List, Dict
|
|
7
|
+
from pydantic import ConfigDict, Field
|
|
8
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
9
|
+
from .regscale_model import RegScaleModel
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class QuestionType(str, Enum):
|
|
13
|
+
"""
|
|
14
|
+
Enum for the QuestionType field in the Questions model.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
ShortAnswer = 0
|
|
18
|
+
LongAnswer = 1
|
|
19
|
+
Instructional = 2
|
|
20
|
+
Date = 3
|
|
21
|
+
PhoneNumber = 4
|
|
22
|
+
Email = 5
|
|
23
|
+
DigitalSignature = 6
|
|
24
|
+
MultipleChoice = 10
|
|
25
|
+
CheckBoxes = 20
|
|
26
|
+
Dropdown = 30
|
|
27
|
+
FileAccess = 50
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AnswerOptions(RegScaleModel):
|
|
31
|
+
answerOption: Optional[str]
|
|
32
|
+
answerScore: Optional[int] = 0
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Questions(RegScaleModel):
|
|
36
|
+
"""
|
|
37
|
+
A class to represent the Questions model in RegScale.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
_module_slug = "questions"
|
|
41
|
+
|
|
42
|
+
id: Optional[int] = None
|
|
43
|
+
parentQuestionnaireId: int = 0
|
|
44
|
+
uuid: Optional[str] = None
|
|
45
|
+
questionType: int = 0
|
|
46
|
+
name: Optional[str] = None
|
|
47
|
+
label: Optional[str] = None
|
|
48
|
+
prompt: Optional[str] = None
|
|
49
|
+
tenantsId: Optional[int] = 1
|
|
50
|
+
createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
51
|
+
dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
52
|
+
dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
53
|
+
isPublic: bool = True
|
|
54
|
+
lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
55
|
+
controlNumber: Optional[str] = None
|
|
56
|
+
section: int = 0
|
|
57
|
+
staticAnswerOptions: Optional[List[Dict]] = None # Adjust the type if it's not a string
|
|
58
|
+
askQuestion: bool = True
|
|
59
|
+
quid: Optional[str] = None
|
|
60
|
+
required: bool = True
|
|
61
|
+
sectionIndex: int = 1
|
|
62
|
+
uploadEnabled: bool = False
|
|
63
|
+
response: Optional[str] = None # Adjust the type if it's not a string
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
67
|
+
"""
|
|
68
|
+
Get endpoints for the Question model.
|
|
69
|
+
|
|
70
|
+
:return: A dictionary of endpoints
|
|
71
|
+
:rtype: ConfigDict
|
|
72
|
+
"""
|
|
73
|
+
return ConfigDict(
|
|
74
|
+
get_all_by_parent_get="/api/{model_slug}/getAllByParent",
|
|
75
|
+
get="/api/{model_slug}/find/{id}",
|
|
76
|
+
insert="/api/{model_slug}/create",
|
|
77
|
+
update="/api/{model_slug}/update",
|
|
78
|
+
delete="/api/{model_slug}/delete/{id}",
|
|
79
|
+
get_new_section_index_post="/api/{model_slug}/getNewSectionIndex",
|
|
80
|
+
update_origin_section_put="/api/{model_slug}/updateOriginSection",
|
|
81
|
+
section_update_from_insert_put="/api/{model_slug}/sectionUpdateFromInsert",
|
|
82
|
+
section_update_from_cancel_put="/api/{model_slug}/sectionUpdateFromCancel",
|
|
83
|
+
index_up_put="/api/{model_slug}/indexUp",
|
|
84
|
+
index_down_put="/api/{model_slug}/indexDown",
|
|
85
|
+
)
|