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,162 @@
|
|
|
1
|
+
"""Module for defining the VulnerabilityMapping model."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Optional, List, Dict, Any
|
|
6
|
+
|
|
7
|
+
from pydantic import Field, ConfigDict
|
|
8
|
+
|
|
9
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
10
|
+
from regscale.models.regscale_models.search import Search
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class VulnerabilityMapping(RegScaleModel):
|
|
14
|
+
"""Represents a mapping between vulnerabilities and assets."""
|
|
15
|
+
|
|
16
|
+
_module_slug = "vulnerabilityMappings"
|
|
17
|
+
_unique_fields = [
|
|
18
|
+
["vulnerabilityId", "assetId", "scanId"],
|
|
19
|
+
]
|
|
20
|
+
_parent_id_field = "scanId"
|
|
21
|
+
|
|
22
|
+
uuid: Optional[str] = None
|
|
23
|
+
vulnerabilityId: int
|
|
24
|
+
assetId: int
|
|
25
|
+
scanId: Optional[int] = None
|
|
26
|
+
securityPlansId: Optional[int] = None
|
|
27
|
+
status: Optional[str] = Field(max_length=450)
|
|
28
|
+
firstSeen: str
|
|
29
|
+
lastSeen: str
|
|
30
|
+
dateClosed: Optional[str] = None
|
|
31
|
+
isPublic: bool = Field(default=False)
|
|
32
|
+
createdById: str = Field(default_factory=RegScaleModel.get_user_id)
|
|
33
|
+
lastUpdatedById: str = Field(default_factory=RegScaleModel.get_user_id)
|
|
34
|
+
dateCreated: str
|
|
35
|
+
dateLastUpdated: Optional[str] = None
|
|
36
|
+
tenantsId: int = Field(default=0)
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
40
|
+
"""
|
|
41
|
+
Get additional endpoints for the API.
|
|
42
|
+
|
|
43
|
+
:return: A dictionary of additional endpoints
|
|
44
|
+
:rtype: ConfigDict
|
|
45
|
+
"""
|
|
46
|
+
return ConfigDict(
|
|
47
|
+
find_by_vulnerability="/api/{model_slug}/findByVulnerability/{vulnerability_id}",
|
|
48
|
+
find_by_asset="/api/{model_slug}/findByAsset/{asset_id}",
|
|
49
|
+
find_by_issue="/api/{model_slug}/findByIssue/{issue_id}",
|
|
50
|
+
find_by_scan="/api/{model_slug}/findByScan/{scan_id}",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
@classmethod
|
|
54
|
+
def find_by_vulnerability(cls, vulnerability_id: int, status: str = "all") -> List["VulnerabilityMapping"]:
|
|
55
|
+
"""
|
|
56
|
+
Get vulnerability mappings by vulnerability ID.
|
|
57
|
+
|
|
58
|
+
:param int vulnerability_id: The vulnerability ID
|
|
59
|
+
:param str status: The status filter (default is "all")
|
|
60
|
+
:return: A list of vulnerability mappings with the given vulnerability ID
|
|
61
|
+
:rtype: List[VulnerabilityMapping]
|
|
62
|
+
"""
|
|
63
|
+
endpoint = cls.get_endpoint("find_by_vulnerability").format(vulnerability_id=vulnerability_id)
|
|
64
|
+
params = {"status": status}
|
|
65
|
+
response = cls._get_api_handler().get(endpoint, params=params)
|
|
66
|
+
results = cls._handle_list_response(response)
|
|
67
|
+
for result in results:
|
|
68
|
+
cls.cache_object(result)
|
|
69
|
+
return results
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def find_by_asset(cls, asset_id: int, status: str = "all") -> List["VulnerabilityMapping"]:
|
|
73
|
+
"""
|
|
74
|
+
Get vulnerability mappings by asset ID.
|
|
75
|
+
|
|
76
|
+
:param int asset_id: The asset ID
|
|
77
|
+
:param str status: The status filter (default is "all")
|
|
78
|
+
:return: A list of vulnerability mappings with the given asset ID
|
|
79
|
+
:rtype: List[VulnerabilityMapping]
|
|
80
|
+
"""
|
|
81
|
+
endpoint = cls.get_endpoint("find_by_asset").format(asset_id=asset_id)
|
|
82
|
+
params = {"status": status}
|
|
83
|
+
response = cls._get_api_handler().get(endpoint, params=params)
|
|
84
|
+
results = cls._handle_list_response(response)
|
|
85
|
+
for result in results:
|
|
86
|
+
cls.cache_object(result)
|
|
87
|
+
return results
|
|
88
|
+
|
|
89
|
+
@classmethod
|
|
90
|
+
def find_by_issue(cls, issue_id: int, status: str = "all") -> List["VulnerabilityMapping"]:
|
|
91
|
+
"""
|
|
92
|
+
Get vulnerability mappings by issue ID.
|
|
93
|
+
|
|
94
|
+
:param int issue_id: The issue ID
|
|
95
|
+
:param str status: The status filter (default is "all")
|
|
96
|
+
:return: A list of vulnerability mappings with the given issue ID
|
|
97
|
+
:rtype: List[VulnerabilityMapping]
|
|
98
|
+
"""
|
|
99
|
+
endpoint = cls.get_endpoint("find_by_issue").format(issue_id=issue_id)
|
|
100
|
+
params = {"status": status}
|
|
101
|
+
response = cls._get_api_handler().get(endpoint, params=params)
|
|
102
|
+
results = cls._handle_list_response(response)
|
|
103
|
+
for result in results:
|
|
104
|
+
cls.cache_object(result)
|
|
105
|
+
return results
|
|
106
|
+
|
|
107
|
+
@classmethod
|
|
108
|
+
def find_by_scan(cls, scan_id: int, status: str = "all") -> List["VulnerabilityMapping"]:
|
|
109
|
+
"""
|
|
110
|
+
Get vulnerability mappings by scan ID.
|
|
111
|
+
|
|
112
|
+
:param int scan_id: The scan ID
|
|
113
|
+
:param str status: The status filter (default is "all")
|
|
114
|
+
:return: A list of vulnerability mappings with the given scan ID
|
|
115
|
+
:rtype: List[VulnerabilityMapping]
|
|
116
|
+
"""
|
|
117
|
+
endpoint = cls.get_endpoint("find_by_scan").format(scan_id=scan_id)
|
|
118
|
+
params = {"status": status}
|
|
119
|
+
response = cls._get_api_handler().get(endpoint, params=params)
|
|
120
|
+
results = cls._handle_list_response(response)
|
|
121
|
+
for result in results:
|
|
122
|
+
cls.cache_object(result)
|
|
123
|
+
return results
|
|
124
|
+
|
|
125
|
+
def create_unique(self) -> "VulnerabilityMapping":
|
|
126
|
+
"""
|
|
127
|
+
Create a VulnerabilityMapping object, using cache to check for existing records.
|
|
128
|
+
|
|
129
|
+
:return: The created or existing VulnerabilityMapping object
|
|
130
|
+
:rtype: VulnerabilityMapping
|
|
131
|
+
"""
|
|
132
|
+
# Check if the object already exists in the cache
|
|
133
|
+
cache_key = self._get_cache_key(self)
|
|
134
|
+
with self._get_lock(cache_key):
|
|
135
|
+
cached_object = self.get_cached_object(cache_key)
|
|
136
|
+
if cached_object:
|
|
137
|
+
return cached_object
|
|
138
|
+
|
|
139
|
+
# If not found, create a new object
|
|
140
|
+
new_object = super().create()
|
|
141
|
+
self.cache_object(new_object)
|
|
142
|
+
return new_object
|
|
143
|
+
|
|
144
|
+
@classmethod
|
|
145
|
+
def get_all_by_parent(
|
|
146
|
+
cls,
|
|
147
|
+
parent_id: int,
|
|
148
|
+
parent_module: Optional[str] = None,
|
|
149
|
+
search: Optional[Search] = None,
|
|
150
|
+
**kwargs: Dict[str, Any],
|
|
151
|
+
) -> List["VulnerabilityMapping"]:
|
|
152
|
+
"""
|
|
153
|
+
Get all vulnerability mappings for a given parent.
|
|
154
|
+
|
|
155
|
+
:param int parent_id: The ID of the parent (scan ID in this case)
|
|
156
|
+
:param Optional[str] parent_module: The module of the parent (not used for VulnerabilityMapping)
|
|
157
|
+
:param Optional[Search] search: Search string (not used for VulnerabilityMapping)
|
|
158
|
+
:return: A list of vulnerability mappings for the given parent
|
|
159
|
+
:rtype: List[VulnerabilityMapping]
|
|
160
|
+
"""
|
|
161
|
+
status = kwargs.get("status", "all")
|
|
162
|
+
return cls.find_by_scan(scan_id=parent_id, status=status)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""RegScale Workflow model"""
|
|
2
|
+
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
from requests import JSONDecodeError
|
|
7
|
+
|
|
8
|
+
from regscale.core.app.api import Api
|
|
9
|
+
from regscale.core.app.application import Application
|
|
10
|
+
from regscale.core.app.utils.app_utils import create_logger
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Workflow(BaseModel):
|
|
14
|
+
id: int = 0
|
|
15
|
+
name: Optional[str] = None
|
|
16
|
+
status: Optional[str] = None
|
|
17
|
+
startDate: Optional[str] = None
|
|
18
|
+
endDate: Optional[str] = None
|
|
19
|
+
currentStep: int = 0
|
|
20
|
+
comments: Optional[str] = None
|
|
21
|
+
createdById: Optional[str] = None
|
|
22
|
+
dateCreated: Optional[str] = None
|
|
23
|
+
lastUpdatedById: Optional[str] = None
|
|
24
|
+
isPublic: bool = True
|
|
25
|
+
dateLastUpdated: Optional[str] = None
|
|
26
|
+
ownerId: Optional[str] = None
|
|
27
|
+
atlasModule: Optional[str] = None
|
|
28
|
+
parentId: Optional[int] = None
|
|
29
|
+
workflowInstanceSteps: List[str] = Field(default_factory=list)
|
|
30
|
+
|
|
31
|
+
def insert_workflow(self, app: Application, template_id: int) -> Optional["Workflow"]:
|
|
32
|
+
"""
|
|
33
|
+
Insert a workflow into the database
|
|
34
|
+
|
|
35
|
+
:param Application app: Application instance
|
|
36
|
+
:param int template_id: Workflow template ID in RegScale
|
|
37
|
+
:return: Newly created Workflow object, or None if unsuccessful
|
|
38
|
+
:rtype: Optional[Workflow]
|
|
39
|
+
"""
|
|
40
|
+
api = Api()
|
|
41
|
+
# Convert the model to a dictionary
|
|
42
|
+
data = self.dict()
|
|
43
|
+
url = f"{app.config['domain']}/api/workflowInstances/createFromTemplate/{template_id}"
|
|
44
|
+
# Make the API call
|
|
45
|
+
response = api.post(url=url, json=data)
|
|
46
|
+
|
|
47
|
+
# Check the response
|
|
48
|
+
if not response.ok:
|
|
49
|
+
response.raise_for_status()
|
|
50
|
+
try:
|
|
51
|
+
workflow = Workflow(**response.json())
|
|
52
|
+
except JSONDecodeError as jex:
|
|
53
|
+
logger = create_logger()
|
|
54
|
+
logger.error("Unable to read workflow:\n%s", jex)
|
|
55
|
+
return workflow or None
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module contains the WorkflowAction model.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
8
|
+
from pydantic import ConfigDict
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class WorkflowAction(RegScaleModel):
|
|
12
|
+
_module_slug = "workflowActions"
|
|
13
|
+
|
|
14
|
+
id: Optional[int] = None
|
|
15
|
+
value: Optional[str] = None
|
|
16
|
+
recordId: Optional[int] = None
|
|
17
|
+
recordModule: Optional[str] = None
|
|
18
|
+
days: Optional[int] = None
|
|
19
|
+
recordTitle: Optional[str] = None
|
|
20
|
+
workflowTemplateId: Optional[int] = None
|
|
21
|
+
workflowInstanceId: Optional[int] = None
|
|
22
|
+
isPublic = True
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
26
|
+
"""
|
|
27
|
+
Get additional endpoints for the WorkflowAction model.
|
|
28
|
+
|
|
29
|
+
:return: A dictionary of additional endpoints
|
|
30
|
+
:rtype: ConfigDict
|
|
31
|
+
"""
|
|
32
|
+
return ConfigDict(
|
|
33
|
+
get_actions="/api/{model_slug}/getActions/{strModule}",
|
|
34
|
+
)
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Optional, List
|
|
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
|
+
from workflow_instance_step import WorkflowInstanceStep
|
|
10
|
+
from workflow_template import WorkflowTemplate
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class WorkflowInstanceStatus(Enum):
|
|
16
|
+
"""
|
|
17
|
+
Enum for workflow instance status.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
PENDING = "Pending"
|
|
21
|
+
APPROVED = "Approved"
|
|
22
|
+
REJECTED = "Rejected"
|
|
23
|
+
COMPLETE = "Complete"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class WorkflowInstance(RegScaleModel):
|
|
27
|
+
_module_slug = "workflowInstances"
|
|
28
|
+
|
|
29
|
+
id: Optional[int] = None
|
|
30
|
+
name: Optional[str] = None
|
|
31
|
+
status: Optional[str] = Field(default=WorkflowInstanceStatus.PENDING.value)
|
|
32
|
+
startDate: Optional[str] = None
|
|
33
|
+
endDate: Optional[str] = None
|
|
34
|
+
currentStep: Optional[int] = None
|
|
35
|
+
comments: Optional[str] = None
|
|
36
|
+
createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
37
|
+
dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
38
|
+
lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
39
|
+
isPublic: Optional[bool] = True
|
|
40
|
+
dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
41
|
+
ownerId: Optional[str] = None
|
|
42
|
+
parentId: Optional[int] = None
|
|
43
|
+
atlasModule: Optional[str] = None
|
|
44
|
+
workflowInstanceSteps: Optional[List[WorkflowInstanceStep]] = None
|
|
45
|
+
tenantsId: Optional[int] = 1
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
49
|
+
"""
|
|
50
|
+
Get additional endpoints for the WorkflowInstance model.
|
|
51
|
+
|
|
52
|
+
:return: A dictionary of additional endpoints
|
|
53
|
+
:rtype: ConfigDict
|
|
54
|
+
"""
|
|
55
|
+
return ConfigDict(
|
|
56
|
+
get_by_parent="/api/{model_slug}/filterWorkflowInstanceByParentId/{intParentID}/{strModule}/id/descending/1/100",
|
|
57
|
+
get_count="/api/{model_slug}/getCount",
|
|
58
|
+
get_open="/api/{model_slug}/getOpen",
|
|
59
|
+
get_by_status="/api/{model_slug}/getByStatus",
|
|
60
|
+
user_open_items_days="/api/{model_slug}/userOpenItemsDays/{strOwner}/{intDays}",
|
|
61
|
+
filter_workflow_instances="/api/{model_slug}/filterWorkflowInstances/{strSearch}/{strStatus}/{strOwner}/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
|
|
62
|
+
filter_workflow_instances_by_user="/api/{model_slug}/filterWorkflowInstancesByUser/{strUser}/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
|
|
63
|
+
approve_step_put="/api/{model_slug}/approveStep/{strUserId}",
|
|
64
|
+
submit_put="/api/{model_slug}/submit/{userId}",
|
|
65
|
+
create_from_module_post="/api/{model_slug}/createFromModule/{intTemplateId}/{strUserId}",
|
|
66
|
+
create_custom_workflow_post="/api/{model_slug}/createCustomWorkflow/{strModule}/{intParentId}",
|
|
67
|
+
reject_step_put="/api/{model_slug}/rejectStep/{strUserId}",
|
|
68
|
+
create_from_template_post="/api/{model_slug}/createFromTemplate/{intTemplateId}",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def get_workflows_by_parent(cls, parent_id: int, parent_module: str) -> List["WorkflowInstance"]:
|
|
73
|
+
"""
|
|
74
|
+
Get all workflows by parent.
|
|
75
|
+
|
|
76
|
+
:param int parent_id: The ID of the parent
|
|
77
|
+
:param str parent_module: The module of the parent
|
|
78
|
+
:return: A list of workflows
|
|
79
|
+
:rtype: List[WorkflowInstance]
|
|
80
|
+
"""
|
|
81
|
+
response = cls._get_api_handler().get(
|
|
82
|
+
endpoint=cls.get_endpoint("get_by_parent").format(intParentID=parent_id, strModule=parent_module)
|
|
83
|
+
)
|
|
84
|
+
if response and response.ok:
|
|
85
|
+
json_data = response.json()
|
|
86
|
+
items = json_data.get("items", [])
|
|
87
|
+
return [WorkflowInstance(**workflow) for workflow in items]
|
|
88
|
+
return []
|
|
89
|
+
|
|
90
|
+
@classmethod
|
|
91
|
+
def find_by_unique(cls, parent_id: int, parent_module: str, name: str) -> Optional["WorkflowInstance"]:
|
|
92
|
+
"""
|
|
93
|
+
Find a object by unique query.
|
|
94
|
+
:param int parent_id: The ID of the parent
|
|
95
|
+
:param str parent_module: The module of the parent
|
|
96
|
+
:param str name: The name of the object
|
|
97
|
+
:return: The functional role
|
|
98
|
+
:rtype: FunctionalRole
|
|
99
|
+
"""
|
|
100
|
+
for instance in cls.get_all_by_parent(parent_id=parent_id, parent_module=parent_module):
|
|
101
|
+
if instance.name == name:
|
|
102
|
+
return instance
|
|
103
|
+
return None
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def create_from_template(cls, template_id: int) -> Optional[int]:
|
|
107
|
+
"""
|
|
108
|
+
Create a workflow instance from a template.
|
|
109
|
+
|
|
110
|
+
:param int template_id: The ID of the template
|
|
111
|
+
:return: The created workflow instance id
|
|
112
|
+
:rtype: Optional[int]
|
|
113
|
+
"""
|
|
114
|
+
workflow_template = WorkflowTemplate.get_object(object_id=template_id)
|
|
115
|
+
if not workflow_template:
|
|
116
|
+
logger.error(f"Failed to find workflow template {template_id}")
|
|
117
|
+
return None
|
|
118
|
+
response = cls._get_api_handler().post(
|
|
119
|
+
endpoint=cls.get_endpoint("create_from_template_post").format(
|
|
120
|
+
model_slug=cls._module_slug, intTemplateId=template_id
|
|
121
|
+
),
|
|
122
|
+
data=workflow_template.model_dump(),
|
|
123
|
+
)
|
|
124
|
+
if response and response.ok:
|
|
125
|
+
return int(response.text)
|
|
126
|
+
else:
|
|
127
|
+
logger.error(f"Failed to create workflow instance from template {template_id}")
|
|
128
|
+
return None
|
|
129
|
+
|
|
130
|
+
@classmethod
|
|
131
|
+
def create_custom_workflow_from_template(
|
|
132
|
+
cls, template_id: int, parent_id: int, parent_module: str
|
|
133
|
+
) -> Optional["WorkflowInstance"]:
|
|
134
|
+
"""
|
|
135
|
+
Create a workflow instance from a template.
|
|
136
|
+
|
|
137
|
+
:param int template_id: The ID of the template
|
|
138
|
+
:param int parent_id: The ID of the parent
|
|
139
|
+
:param str parent_module: The module of the parent
|
|
140
|
+
:return: The created workflow instance id
|
|
141
|
+
:rtype: Optional[int]
|
|
142
|
+
"""
|
|
143
|
+
workflow_template = WorkflowTemplate.get_object(object_id=template_id)
|
|
144
|
+
steps = workflow_template.workflowTemplateSteps
|
|
145
|
+
if not workflow_template:
|
|
146
|
+
logger.error(f"Failed to find workflow template {template_id}")
|
|
147
|
+
return None
|
|
148
|
+
response = cls._get_api_handler().post(
|
|
149
|
+
endpoint=cls.get_endpoint("create_custom_workflow_post").format(
|
|
150
|
+
model_slug=cls._module_slug, strModule=parent_module, intParentId=parent_id
|
|
151
|
+
),
|
|
152
|
+
data=[step.model_dump() for step in steps],
|
|
153
|
+
)
|
|
154
|
+
if response and response.ok:
|
|
155
|
+
return WorkflowInstance(**response.json())
|
|
156
|
+
else:
|
|
157
|
+
logger.error(f"Failed to create workflow instance from template {template_id}")
|
|
158
|
+
return None
|
|
159
|
+
|
|
160
|
+
@classmethod
|
|
161
|
+
def create_custom_workflow_from_template_with_group(
|
|
162
|
+
cls, template_id: int, parent_id: int, parent_module: str, group_id: int, group_name: str
|
|
163
|
+
) -> Optional["WorkflowInstance"]:
|
|
164
|
+
"""
|
|
165
|
+
Create a workflow instance from a template.
|
|
166
|
+
|
|
167
|
+
:param int template_id: The ID of the template
|
|
168
|
+
:param int parent_id: The ID of the parent
|
|
169
|
+
:param str parent_module: The module of the parent
|
|
170
|
+
:param int group_id: The ID of the group
|
|
171
|
+
:param str group_name: The name of the group
|
|
172
|
+
:return: The created workflow instance id
|
|
173
|
+
:rtype: Optional[int]
|
|
174
|
+
"""
|
|
175
|
+
workflow_template = WorkflowTemplate.get_object(object_id=template_id)
|
|
176
|
+
steps = workflow_template.workflowTemplateSteps
|
|
177
|
+
for step in steps:
|
|
178
|
+
if step.name == "Automated Conflict of Interest Check":
|
|
179
|
+
continue
|
|
180
|
+
step.name = f"{step.name} - {group_name}" if group_name else step.name
|
|
181
|
+
step.groupsId = group_id
|
|
182
|
+
|
|
183
|
+
if not workflow_template:
|
|
184
|
+
logger.error(f"Failed to find workflow template {template_id}")
|
|
185
|
+
return None
|
|
186
|
+
response = cls._get_api_handler().post(
|
|
187
|
+
endpoint=cls.get_endpoint("create_custom_workflow_post").format(
|
|
188
|
+
model_slug=cls._module_slug, strModule=parent_module, intParentId=parent_id
|
|
189
|
+
),
|
|
190
|
+
data=[step.model_dump() for step in steps],
|
|
191
|
+
)
|
|
192
|
+
if response and response.ok:
|
|
193
|
+
return WorkflowInstance(**response.json())
|
|
194
|
+
else:
|
|
195
|
+
logger.error(f"Failed to create workflow instance from template {template_id}")
|
|
196
|
+
return None
|
|
197
|
+
|
|
198
|
+
def create_custom_workflow(self, module: str, parent_id: int) -> Optional[int]:
|
|
199
|
+
"""
|
|
200
|
+
Create a custom workflow instance.
|
|
201
|
+
|
|
202
|
+
:param str module: The module of the parent
|
|
203
|
+
:param int parent_id: The ID of the parent
|
|
204
|
+
:return: The created workflow instance id
|
|
205
|
+
:rtype: Optional[int]
|
|
206
|
+
"""
|
|
207
|
+
response = selfcls._get_api_handler().post(
|
|
208
|
+
endpoint=self.get_endpoint("create_custom_workflow_post").format(
|
|
209
|
+
model_slug=self._module_slug, strModule=module, intParentId=parent_id
|
|
210
|
+
),
|
|
211
|
+
data=self.dict(),
|
|
212
|
+
)
|
|
213
|
+
if response and response.ok:
|
|
214
|
+
return int(response.text)
|
|
215
|
+
else:
|
|
216
|
+
logger.error(f"Failed to create custom workflow instance from module {module}. Error: {response.text}")
|
|
217
|
+
return None
|
|
218
|
+
|
|
219
|
+
def approve_step(self, user_id: str) -> bool:
|
|
220
|
+
"""
|
|
221
|
+
Approve a step in a workflow instance.
|
|
222
|
+
|
|
223
|
+
:param str user_id: The ID of the user
|
|
224
|
+
:return: True if successful
|
|
225
|
+
:rtype: bool
|
|
226
|
+
"""
|
|
227
|
+
response = selfcls._get_api_handler().put(
|
|
228
|
+
endpoint=self.get_endpoint("approve_step_put").format(model_slug=self._module_slug, strUserId=user_id),
|
|
229
|
+
data=self.dict(),
|
|
230
|
+
)
|
|
231
|
+
if getattr(response, "ok", False):
|
|
232
|
+
return True
|
|
233
|
+
else:
|
|
234
|
+
logger.error(f"Failed to approve step for {self.name}")
|
|
235
|
+
return False
|
|
236
|
+
|
|
237
|
+
def reject_step(self, user_id: str) -> bool:
|
|
238
|
+
"""
|
|
239
|
+
Reject a step in a workflow instance.
|
|
240
|
+
|
|
241
|
+
:param str user_id: The ID of the user
|
|
242
|
+
:return: True if successful
|
|
243
|
+
:rtype: bool
|
|
244
|
+
"""
|
|
245
|
+
response = selfcls._get_api_handler().put(
|
|
246
|
+
endpoint=self.get_endpoint("reject_step_put").format(model_slug=self._module_slug, strUserId=user_id),
|
|
247
|
+
data=self.dict(),
|
|
248
|
+
)
|
|
249
|
+
if getattr(response, "ok", False):
|
|
250
|
+
return True
|
|
251
|
+
else:
|
|
252
|
+
logger.error(f"Failed to reject step for {self.name}")
|
|
253
|
+
return False
|
|
254
|
+
|
|
255
|
+
def approve_all_steps(self, user_id: str) -> None:
|
|
256
|
+
"""
|
|
257
|
+
Approve all steps in a workflow instance.
|
|
258
|
+
|
|
259
|
+
:param str user_id: The ID of the user
|
|
260
|
+
:rtype: None
|
|
261
|
+
"""
|
|
262
|
+
for step in WorkflowInstanceStep.get_all_by_parent(
|
|
263
|
+
parent_id=self.id,
|
|
264
|
+
parent_module=self.get_module_slug(),
|
|
265
|
+
):
|
|
266
|
+
if step.order not in [0, 1000]:
|
|
267
|
+
self.currentStep = step.order
|
|
268
|
+
self.comments = "<p>I Approve</p>"
|
|
269
|
+
self.approve_step(user_id=user_id)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module contains the WorkflowInstanceStep model class that represents a workflow instance step in the RegScale application.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional, Union
|
|
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
|
+
from enum import Enum
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class WorkflowInstanceStepType(str, Enum):
|
|
15
|
+
"""
|
|
16
|
+
Enum for workflow instance step type.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
MANAGER = "Manager"
|
|
20
|
+
GROUP = "Group"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class WorkflowInstanceStepExecutionType(str, Enum):
|
|
24
|
+
"""
|
|
25
|
+
Enum for workflow instance step execution type.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
SEQUENTIAL = "Sequential"
|
|
29
|
+
PARALLEL = "Parallel"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class WorkflowInstanceStepStatus(str, Enum):
|
|
33
|
+
"""
|
|
34
|
+
Enum for workflow instance step status.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
PENDING = "Pending"
|
|
38
|
+
APPROVED = "Approved"
|
|
39
|
+
REJECTED = "Rejected"
|
|
40
|
+
COMPLETE = "Complete"
|
|
41
|
+
SUBMITTED = "Submitted"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class WorkflowInstanceStep(RegScaleModel):
|
|
45
|
+
_module_slug = "workflowInstanceSteps"
|
|
46
|
+
|
|
47
|
+
id: Optional[int] = None
|
|
48
|
+
workflowInstanceId: Optional[int] = None
|
|
49
|
+
name: Optional[str] = None
|
|
50
|
+
comments: Optional[str] = None
|
|
51
|
+
order: Optional[int] = 1
|
|
52
|
+
status: Optional[str] = None
|
|
53
|
+
startDate: Optional[str] = None
|
|
54
|
+
endDate: Optional[str] = None
|
|
55
|
+
actionType: Optional[str] = None
|
|
56
|
+
executionType: Optional[str] = None
|
|
57
|
+
createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
58
|
+
dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
59
|
+
lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
60
|
+
isPublic: Optional[bool] = True
|
|
61
|
+
dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
62
|
+
groupsId: Optional[int] = None
|
|
63
|
+
tenantsId: Optional[int] = 1
|
|
64
|
+
stepType: Optional[str] = None
|
|
65
|
+
assignedToId: Optional[str] = None
|
|
66
|
+
functionalRoleId: Optional[int] = None
|
|
67
|
+
parentId: Optional[int] = None
|
|
68
|
+
parentModule: Optional[str] = None
|
|
69
|
+
|
|
70
|
+
@staticmethod
|
|
71
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
72
|
+
"""
|
|
73
|
+
Get additional endpoints for the WorkflowInstanceStep model.
|
|
74
|
+
|
|
75
|
+
:return: A dictionary of additional endpoints
|
|
76
|
+
:rtype: ConfigDict
|
|
77
|
+
"""
|
|
78
|
+
return ConfigDict(
|
|
79
|
+
get_by_parent="/api/{model_slug}/getByParent/{intParentID}",
|
|
80
|
+
filter_workflow_instance_steps_by_parent="/api/{model_slug}/filterWorkflowInstanceStepsByParent/{intWorkflowInstanceID}/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
|
|
81
|
+
update_workflow_instance_step_put="/api/{model_slug}/{id}",
|
|
82
|
+
get_workflow_instance_step="/api/{model_slug}/{id}",
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def find_by_unique(cls, workflow_instance_id: int, field_name: str, field_value: Union[str, int]):
|
|
87
|
+
"""
|
|
88
|
+
Find a object by unique query.
|
|
89
|
+
:param workflow_instance_id: The workflow instance ID
|
|
90
|
+
:param field_name: The field name
|
|
91
|
+
:param field_value: The field value
|
|
92
|
+
:return: The functional role
|
|
93
|
+
:rtype: FunctionalRole
|
|
94
|
+
"""
|
|
95
|
+
for instance in cls.get_all_by_parent(parent_id=workflow_instance_id, parent_module=None):
|
|
96
|
+
if getattr(instance, field_name) == field_value:
|
|
97
|
+
return instance
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
def get_by_parent(cls, parent_id: int):
|
|
102
|
+
"""
|
|
103
|
+
Get workflow instance steps by parent ID.
|
|
104
|
+
|
|
105
|
+
:param parent_id: The parent ID
|
|
106
|
+
:return: A list of workflow instance steps
|
|
107
|
+
:rtype: List[WorkflowInstanceStep]
|
|
108
|
+
"""
|
|
109
|
+
response = cls._get_api_handler().get(
|
|
110
|
+
endpoint=cls.get_endpoint("get_by_parent").format(model_slug=cls._module_slug, intParentID=parent_id)
|
|
111
|
+
)
|
|
112
|
+
if response and response.ok:
|
|
113
|
+
return [WorkflowInstanceStep(**step) for step in response.json()]
|
|
114
|
+
return []
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module contains the WorkflowTemplate model.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional, List
|
|
6
|
+
|
|
7
|
+
from pydantic import ConfigDict, Field
|
|
8
|
+
|
|
9
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
10
|
+
from workflow_template_step import WorkflowTemplateStep
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class WorkflowTemplate(RegScaleModel):
|
|
14
|
+
_module_slug = "workflowTemplates"
|
|
15
|
+
|
|
16
|
+
id: Optional[int] = None
|
|
17
|
+
name: Optional[str] = None
|
|
18
|
+
status: Optional[str] = None
|
|
19
|
+
createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
20
|
+
dateCreated: Optional[str] = None
|
|
21
|
+
lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
22
|
+
isPublic: Optional[bool] = None
|
|
23
|
+
dateLastUpdated: Optional[str] = None
|
|
24
|
+
atlasModule: Optional[str] = None
|
|
25
|
+
workflowTemplateSteps: Optional[List[WorkflowTemplateStep]] = None
|
|
26
|
+
tenantsId: int = 1
|
|
27
|
+
|
|
28
|
+
@staticmethod
|
|
29
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
30
|
+
"""
|
|
31
|
+
Get additional endpoints for the WorkflowTemplate model.
|
|
32
|
+
|
|
33
|
+
:return: A dictionary of additional endpoints
|
|
34
|
+
:rtype: ConfigDict
|
|
35
|
+
"""
|
|
36
|
+
return ConfigDict(
|
|
37
|
+
get_count="/api/{model_slug}/getCount",
|
|
38
|
+
get_by_atlas_module="/api/{model_slug}/getByAtlasModule/{strModule}",
|
|
39
|
+
filter_workflow_templates="/api/{model_slug}/filterWorkflowTemplates/{strSearch}/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def get_by_module_slug(cls, module: str) -> List["WorkflowTemplate"]:
|
|
44
|
+
"""
|
|
45
|
+
Get all workflow templates by atlas module.
|
|
46
|
+
|
|
47
|
+
:param str module: The module of the parent
|
|
48
|
+
:return: A list of workflow templates
|
|
49
|
+
:rtype: List["WorkflowTemplate"]
|
|
50
|
+
"""
|
|
51
|
+
response = cls._get_api_handler().get(
|
|
52
|
+
endpoint=cls.get_endpoint("get_by_atlas_module").format(model_slug=cls._module_slug, strModule=module)
|
|
53
|
+
)
|
|
54
|
+
if response and response.ok:
|
|
55
|
+
return [cls(**o) for o in response.json()]
|
|
56
|
+
else:
|
|
57
|
+
cls.log_response_error(response=response)
|
|
58
|
+
return []
|