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
regscale/utils/string.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""Define commonly used methods for strings."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
ANSI_ESCAPE_REGEX = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def remove_ansi_escape_sequences(text: str) -> str:
|
|
10
|
+
"""Remove all ANSI escape sequences from a text
|
|
11
|
+
|
|
12
|
+
:param str text: a string to remove ANSI escape sequences from
|
|
13
|
+
:return: a string with no ANSI escape sequences
|
|
14
|
+
:rtype: str
|
|
15
|
+
"""
|
|
16
|
+
return ANSI_ESCAPE_REGEX.sub("", text)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def replace_unknown_spaces_and_newlines(input_string: str) -> str:
|
|
20
|
+
"""Replace unknown spaces and newlines with a single space
|
|
21
|
+
|
|
22
|
+
:param str input_string: a string to replace unknown spaces and newlines with a single space
|
|
23
|
+
:return: a string with unknown spaces and newlines replaced with a single space
|
|
24
|
+
:rtype: str
|
|
25
|
+
"""
|
|
26
|
+
return re.sub(r"\s+", " ", input_string)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def extract_double_curly_braces_contents(query_string: str) -> list[str]:
|
|
30
|
+
"""Extract the contents of double curly braces from a string
|
|
31
|
+
|
|
32
|
+
:param str query_string: a string to extract the contents of double curly braces from
|
|
33
|
+
:return: a list of strings that were contained within double curly braces
|
|
34
|
+
:rtype: list[str]
|
|
35
|
+
"""
|
|
36
|
+
pattern = r"{{(.*?)}}"
|
|
37
|
+
return re.findall(pattern, query_string)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def extract_dag_run_conf_key(query_string: str) -> Optional[str]:
|
|
41
|
+
"""
|
|
42
|
+
Extract the key from a dag_run.conf key-value pair
|
|
43
|
+
|
|
44
|
+
:param str query_string: a string to extract the key from a dag_run.conf key-value pair
|
|
45
|
+
:return: the key from a dag_run.conf key-value pair
|
|
46
|
+
:rtype: Optional[str]
|
|
47
|
+
"""
|
|
48
|
+
pattern = r"dag_run\.conf\[['\"]([^'\"]+)['\"]\]"
|
|
49
|
+
match = re.search(pattern, query_string)
|
|
50
|
+
return match[1] if match else None
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def extract_param(query_string: str) -> Optional[list]:
|
|
54
|
+
"""
|
|
55
|
+
Extract the parameter from a params key-value pair
|
|
56
|
+
|
|
57
|
+
:param str query_string: a string to extract the parameter from a params key-value pair
|
|
58
|
+
:return: the parameter from a params key-value pair
|
|
59
|
+
:rtype: Optional[list]
|
|
60
|
+
"""
|
|
61
|
+
pattern = r"\bparams\.(\w+)\s.*"
|
|
62
|
+
matches = re.findall(pattern, query_string)
|
|
63
|
+
return matches[0] if matches else None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def levenshtein_distance(first_string: str, second_string: str) -> int:
|
|
67
|
+
"""
|
|
68
|
+
Calculate the Levenshtein distance between two strings
|
|
69
|
+
|
|
70
|
+
:param str first_string: the first string to compare
|
|
71
|
+
:param str second_string: the second string to compare
|
|
72
|
+
:return: the Levenshtein distance between two strings
|
|
73
|
+
:rtype: int
|
|
74
|
+
"""
|
|
75
|
+
if len(first_string) < len(second_string):
|
|
76
|
+
return levenshtein_distance(second_string, first_string)
|
|
77
|
+
|
|
78
|
+
if len(second_string) == 0:
|
|
79
|
+
return len(first_string)
|
|
80
|
+
|
|
81
|
+
previous_row = range(len(second_string) + 1)
|
|
82
|
+
for i, c1 in enumerate(first_string):
|
|
83
|
+
current_row = [i + 1]
|
|
84
|
+
for j, c2 in enumerate(second_string):
|
|
85
|
+
insertions = previous_row[j + 1] + 1
|
|
86
|
+
deletions = current_row[j] + 1
|
|
87
|
+
substitutions = previous_row[j] + (c1 != c2)
|
|
88
|
+
current_row.append(min(insertions, deletions, substitutions))
|
|
89
|
+
previous_row = current_row
|
|
90
|
+
|
|
91
|
+
return previous_row[-1]
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def parse_last_element(string: str, split_str: Optional[str] = "/") -> str:
|
|
95
|
+
"""
|
|
96
|
+
Function to parse last element of a string
|
|
97
|
+
|
|
98
|
+
:param str string: String to parse
|
|
99
|
+
:param str split_str: String to split the string
|
|
100
|
+
:return: Last element of the string
|
|
101
|
+
:rtype: str
|
|
102
|
+
"""
|
|
103
|
+
try:
|
|
104
|
+
return string.split(split_str)[-1]
|
|
105
|
+
except IndexError:
|
|
106
|
+
return ""
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def generate_html_table_from_dict(data: dict) -> str:
|
|
110
|
+
"""
|
|
111
|
+
Function to map all key-value pairs to a description HTML Table
|
|
112
|
+
|
|
113
|
+
:param dict data: Data from Microsoft Defender
|
|
114
|
+
:return: HTML table as a string
|
|
115
|
+
:rtype: str
|
|
116
|
+
"""
|
|
117
|
+
description = "<table>"
|
|
118
|
+
for key, value in data.items():
|
|
119
|
+
description += f"<tr><td>{key}</td><td>{value}</td></tr>"
|
|
120
|
+
description += "</table>"
|
|
121
|
+
return description
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""Utility functions for interacting with the Synqly API"""
|
|
2
|
+
|
|
3
|
+
import signal
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
# Synqly Python SDK imports
|
|
8
|
+
from synqly import management as mgmt
|
|
9
|
+
from synqly.engine.client import SynqlyEngine
|
|
10
|
+
from synqly.management.client import SynqlyManagement
|
|
11
|
+
from regscale.core.app.utils.app_utils import create_logger
|
|
12
|
+
|
|
13
|
+
logger = create_logger()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# This class is an example of a multi-tenant application, meant
|
|
17
|
+
# to represent your application or product. It contains a pool of tenants, each
|
|
18
|
+
# of which might represent a user or organization within your application.
|
|
19
|
+
#
|
|
20
|
+
# This example omits application specific logic, focusing instead on the
|
|
21
|
+
# steps required to configure a Synqly Integration for each tenant.
|
|
22
|
+
class App:
|
|
23
|
+
"""
|
|
24
|
+
This class is an example of a multi-tenant application, meant
|
|
25
|
+
to represent your application or product. It contains a pool of tenants, each
|
|
26
|
+
of which might represent a user or organization within your application.
|
|
27
|
+
|
|
28
|
+
This example omits application specific logic, focusing instead on the
|
|
29
|
+
steps required to configure a Synqly Integration for each tenant.
|
|
30
|
+
|
|
31
|
+
Parameters:
|
|
32
|
+
connector_type - The target Connector. Example: "ticketing"
|
|
33
|
+
|
|
34
|
+
Attributes:
|
|
35
|
+
connector_type - The target Connector. Example: "ticketing"
|
|
36
|
+
tenants - A dictionary of Tenant objects, keyed by tenant name.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, connector_type):
|
|
40
|
+
self.tenants = {}
|
|
41
|
+
self.connector_type = connector_type
|
|
42
|
+
# Initialize signal handlers to intercept Ctrl-C and perform cleanup
|
|
43
|
+
signal.signal(signal.SIGINT, lambda signal, frame: self._cleanup_handler())
|
|
44
|
+
signal.signal(signal.SIGTERM, lambda signal, frame: self._cleanup_handler())
|
|
45
|
+
self.terminated = False
|
|
46
|
+
|
|
47
|
+
def _cleanup_handler(self):
|
|
48
|
+
"""
|
|
49
|
+
Deletes Synqly resources created by the example program.
|
|
50
|
+
"""
|
|
51
|
+
if len(self.tenants) != 0:
|
|
52
|
+
logger.info("\nCleaning up Synqly Resources:")
|
|
53
|
+
for tenant in self.tenants.values():
|
|
54
|
+
# Delete the Synqly Account
|
|
55
|
+
tenant.synqly_management_client.accounts.delete(tenant.synqly_account_id)
|
|
56
|
+
logger.debug("Cleaned up Account " + tenant.synqly_account_id)
|
|
57
|
+
self.tenants = {}
|
|
58
|
+
self.terminated = True
|
|
59
|
+
logger.info("Cleanup complete.")
|
|
60
|
+
|
|
61
|
+
def new_tenant(self, synqly_org_token: str, new_tenant_name: str):
|
|
62
|
+
"""
|
|
63
|
+
Adds a new "tenant" to the App. A tenant represents a user or
|
|
64
|
+
organization within your application.
|
|
65
|
+
|
|
66
|
+
:param str synqly_org_token: The Synqly Organization token
|
|
67
|
+
:param str new_tenant_name: The name of the new tenant
|
|
68
|
+
:raises ValueError: If the tenant already exists
|
|
69
|
+
"""
|
|
70
|
+
# Make sure the tenant doesn't already exist
|
|
71
|
+
for tenant in self.tenants.values():
|
|
72
|
+
if tenant.synqly_account_id == new_tenant_name:
|
|
73
|
+
raise ValueError("Duplicate tenant id: " + id)
|
|
74
|
+
|
|
75
|
+
"""
|
|
76
|
+
Create a Synqly Management API client. The client stores a token,
|
|
77
|
+
allowing us to make calls to the Synqly Management API. The Management
|
|
78
|
+
API is used to create Synqly Accounts and Integrations.
|
|
79
|
+
"""
|
|
80
|
+
# (Optional) configure a custom httpx_client so that all errors are retried
|
|
81
|
+
transport = httpx.HTTPTransport(retries=3)
|
|
82
|
+
management_client = SynqlyManagement(
|
|
83
|
+
token=synqly_org_token,
|
|
84
|
+
httpx_client=httpx.Client(transport=transport),
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
"""
|
|
88
|
+
Each tenant needs an associated Account in Synqly, so we create that now.
|
|
89
|
+
"""
|
|
90
|
+
account_request = mgmt.CreateAccountRequest(fullname=new_tenant_name)
|
|
91
|
+
account_response = management_client.accounts.create(request=account_request)
|
|
92
|
+
account_id = account_response.result.account.id
|
|
93
|
+
|
|
94
|
+
self.tenants[new_tenant_name] = Tenant(
|
|
95
|
+
tenant_name=new_tenant_name,
|
|
96
|
+
synqly_account_id=account_id,
|
|
97
|
+
synqly_management_client=management_client,
|
|
98
|
+
# The Synqly Engine client will be initialized in configure_integration,
|
|
99
|
+
# so we leave it as None for now.
|
|
100
|
+
synqly_engine_client=None,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
def configure_integration(self, tenant_name: str, provider_config: mgmt.ProviderConfig):
|
|
104
|
+
"""
|
|
105
|
+
Configures a Synqly Integration for a simulated tenant
|
|
106
|
+
|
|
107
|
+
:param str tenant_name: The name of the tenant
|
|
108
|
+
:param mgmt.ProviderConfig provider_config: The provider configuration
|
|
109
|
+
:raises TenantNotFoundException: If the tenant name is not found
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
# Locate the tenant in the App's tenant pool
|
|
113
|
+
if tenant_name not in self.tenants.keys():
|
|
114
|
+
raise TenantNotFoundException(tenant_name + " not found")
|
|
115
|
+
|
|
116
|
+
tenant = self.tenants[tenant_name]
|
|
117
|
+
|
|
118
|
+
# Use the Management API to create a Synqly Integration
|
|
119
|
+
integration_req = mgmt.CreateIntegrationRequest(
|
|
120
|
+
fullname="Python SDK Integration",
|
|
121
|
+
provider_config=provider_config,
|
|
122
|
+
)
|
|
123
|
+
integration_resp = tenant.synqly_management_client.integrations.create(
|
|
124
|
+
account_id=tenant.synqly_account_id, request=integration_req
|
|
125
|
+
)
|
|
126
|
+
logger.debug(
|
|
127
|
+
"Created {} Integration '{}' for {}".format(
|
|
128
|
+
integration_resp.result.integration.category,
|
|
129
|
+
integration_resp.result.integration.id,
|
|
130
|
+
tenant_name,
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Add Synqly Engine client to the Tenant for use in the background job
|
|
135
|
+
self.tenants[tenant_name].synqly_engine_client = SynqlyEngine(
|
|
136
|
+
token=integration_resp.result.token.access.secret,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class Tenant:
|
|
141
|
+
"""
|
|
142
|
+
Represents a tenant within the application. A tenant could be a user,
|
|
143
|
+
organization, or any other entity for which it would make sense to create
|
|
144
|
+
an Integration.
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
def __init__(
|
|
148
|
+
self,
|
|
149
|
+
tenant_name,
|
|
150
|
+
synqly_account_id,
|
|
151
|
+
synqly_management_client,
|
|
152
|
+
synqly_engine_client,
|
|
153
|
+
):
|
|
154
|
+
self.tenant_name = tenant_name
|
|
155
|
+
self.synqly_account_id = synqly_account_id
|
|
156
|
+
self.synqly_management_client = synqly_management_client
|
|
157
|
+
self.synqly_engine_client = synqly_engine_client
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class TenantNotFoundException(Exception):
|
|
161
|
+
"""
|
|
162
|
+
Exception raised when a tenant is not found
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
pass
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Use of importing the threading module from the core.utils package
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .threadhandler import ThreadManager
|
|
6
|
+
from .threadsafe_counter import ThreadSafeCounter
|
|
7
|
+
from .threadsafe_dict import ThreadSafeDict
|
|
8
|
+
from .threadsafe_list import ThreadSafeList
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Thread handler to create and start threads"""
|
|
4
|
+
|
|
5
|
+
from concurrent.futures import ThreadPoolExecutor, TimeoutError, as_completed
|
|
6
|
+
from typing import Any, Callable, List, Tuple, Union
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ThreadManager:
|
|
10
|
+
"""
|
|
11
|
+
Class to manage threads and tasks
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, max_workers: int = 20):
|
|
15
|
+
self.executor = ThreadPoolExecutor(max_workers=max_workers)
|
|
16
|
+
self.futures = []
|
|
17
|
+
|
|
18
|
+
def submit_task(self, func: Callable, *args, **kwargs) -> None:
|
|
19
|
+
"""
|
|
20
|
+
Submit a task to the executor
|
|
21
|
+
|
|
22
|
+
:param Callable func: Function to execute
|
|
23
|
+
:rtype: None
|
|
24
|
+
"""
|
|
25
|
+
future = self.executor.submit(func, *args, **kwargs)
|
|
26
|
+
self.futures.append(future)
|
|
27
|
+
|
|
28
|
+
def submit_tasks_from_list(self, func: Callable, items: List[Any], *args, **kwargs) -> None:
|
|
29
|
+
"""
|
|
30
|
+
Submit multiple tasks to the executor, used for a list of items
|
|
31
|
+
|
|
32
|
+
:param Callable func: Function to execute
|
|
33
|
+
:param List[Any] items: List of items to process
|
|
34
|
+
:rtype: None
|
|
35
|
+
"""
|
|
36
|
+
for item in items:
|
|
37
|
+
self.submit_task(func, item, *args, **kwargs)
|
|
38
|
+
|
|
39
|
+
def execute_and_verify(
|
|
40
|
+
self,
|
|
41
|
+
timeout: int = None,
|
|
42
|
+
check_for_failures: bool = True,
|
|
43
|
+
terminate_after: bool = False,
|
|
44
|
+
return_passed: bool = False,
|
|
45
|
+
) -> Union[List[Tuple[bool, Any]], List[Any]]:
|
|
46
|
+
"""
|
|
47
|
+
Execute the tasks and verify if they were successful
|
|
48
|
+
|
|
49
|
+
:param int timeout: Timeout for the tasks
|
|
50
|
+
:param bool check_for_failures: Whether to check for failures, default True
|
|
51
|
+
:param bool terminate_after: Whether to terminate the executor after the tasks are completed, default False
|
|
52
|
+
:param bool return_passed: Whether to return only the passed tasks, default False
|
|
53
|
+
:return: List of tuples with a bool indicating success & the result, or list of results if return_passed is True
|
|
54
|
+
:rtype: Union[List[Tuple[bool, Any]], List[Any]]
|
|
55
|
+
"""
|
|
56
|
+
results = []
|
|
57
|
+
try:
|
|
58
|
+
for future in as_completed(self.futures, timeout=timeout):
|
|
59
|
+
try:
|
|
60
|
+
result = future.result()
|
|
61
|
+
results.append((True, result))
|
|
62
|
+
except TimeoutError:
|
|
63
|
+
results.append((False, "Task timed out"))
|
|
64
|
+
except Exception as e:
|
|
65
|
+
results.append((False, str(e)))
|
|
66
|
+
finally:
|
|
67
|
+
self.futures = []
|
|
68
|
+
if terminate_after:
|
|
69
|
+
self.shutdown()
|
|
70
|
+
if check_for_failures:
|
|
71
|
+
import logging
|
|
72
|
+
|
|
73
|
+
logger = logging.getLogger(__name__)
|
|
74
|
+
for success, result in results:
|
|
75
|
+
if not success:
|
|
76
|
+
logger.error(f"Task failed with error: {result}")
|
|
77
|
+
if return_passed:
|
|
78
|
+
return [result for success, result in results if success]
|
|
79
|
+
# clear the futures list
|
|
80
|
+
return results
|
|
81
|
+
|
|
82
|
+
def shutdown(self, wait: bool = True) -> None:
|
|
83
|
+
"""
|
|
84
|
+
Shutdown the executor
|
|
85
|
+
|
|
86
|
+
:param bool wait: Whether to wait for the tasks to complete
|
|
87
|
+
:rtype: None
|
|
88
|
+
"""
|
|
89
|
+
self.executor.shutdown(wait=wait)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def create_threads(process: Callable, args: Tuple, thread_count: int) -> None:
|
|
93
|
+
"""
|
|
94
|
+
Function to create x threads using ThreadPoolExecutor
|
|
95
|
+
|
|
96
|
+
:param Callable process: function for the threads to execute
|
|
97
|
+
:param Tuple args: args for the provided process
|
|
98
|
+
:param int thread_count: # of threads needed
|
|
99
|
+
:rtype: None
|
|
100
|
+
"""
|
|
101
|
+
# set max threads
|
|
102
|
+
from regscale.core.app.application import Application
|
|
103
|
+
|
|
104
|
+
app = Application()
|
|
105
|
+
max_threads = app.config["maxThreads"]
|
|
106
|
+
if threads := min(thread_count, max_threads):
|
|
107
|
+
# start the threads with the number of threads allowed
|
|
108
|
+
with ThreadPoolExecutor(max_workers=threads) as executor:
|
|
109
|
+
# iterate and start the threads that were requested
|
|
110
|
+
for thread in range(threads):
|
|
111
|
+
# assign each thread the passed process and args along with the thread number
|
|
112
|
+
executor.submit(process, args, thread)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def thread_assignment(thread: int, total_items: int) -> list:
|
|
116
|
+
"""
|
|
117
|
+
Function to iterate through items and returns a list the
|
|
118
|
+
provided thread should be assigned and use during its execution
|
|
119
|
+
|
|
120
|
+
:param int thread: current thread number
|
|
121
|
+
:param int total_items: Total # of items to process with threads
|
|
122
|
+
:return: List of items to process for the given thread
|
|
123
|
+
:rtype: list
|
|
124
|
+
"""
|
|
125
|
+
from regscale.core.app.application import Application
|
|
126
|
+
|
|
127
|
+
app = Application()
|
|
128
|
+
# set max threads
|
|
129
|
+
max_threads = app.config["maxThreads"]
|
|
130
|
+
|
|
131
|
+
return [x for x in range(total_items) if x % max_threads == thread]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module contains the ThreadSafeCounter class, which is a thread-safe counter.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import threading
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ThreadSafeCounter:
|
|
9
|
+
"""
|
|
10
|
+
Class to create a thread-safe counter
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self.value: int = 0
|
|
15
|
+
self._lock = threading.Lock()
|
|
16
|
+
|
|
17
|
+
def increment(self) -> int:
|
|
18
|
+
"""
|
|
19
|
+
Increment the counter by 1
|
|
20
|
+
|
|
21
|
+
:return: The new value of the counter after incrementing
|
|
22
|
+
:rtype: int
|
|
23
|
+
"""
|
|
24
|
+
with self._lock:
|
|
25
|
+
self.value += 1
|
|
26
|
+
return self.value
|
|
27
|
+
|
|
28
|
+
def decrement(self) -> int:
|
|
29
|
+
"""
|
|
30
|
+
Decrement the counter by 1
|
|
31
|
+
|
|
32
|
+
:return: The new value of the counter after decrementing
|
|
33
|
+
:rtype: int
|
|
34
|
+
"""
|
|
35
|
+
with self._lock:
|
|
36
|
+
self.value -= 1
|
|
37
|
+
return self.value
|
|
38
|
+
|
|
39
|
+
def set(self, value: int) -> None:
|
|
40
|
+
"""
|
|
41
|
+
Set the counter to a value
|
|
42
|
+
|
|
43
|
+
:param int value: Value to set the counter to
|
|
44
|
+
:rtype: None
|
|
45
|
+
"""
|
|
46
|
+
with self._lock:
|
|
47
|
+
self.value = value
|