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,196 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Dataclass for a RegScale Threat"""
|
|
4
|
+
|
|
5
|
+
# standard python imports
|
|
6
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
7
|
+
from typing import Any, List, Optional, Union
|
|
8
|
+
|
|
9
|
+
from pydantic import ConfigDict, Field
|
|
10
|
+
|
|
11
|
+
from regscale.core.app.api import Api
|
|
12
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
13
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Threat(RegScaleModel):
|
|
17
|
+
"""Threat Model"""
|
|
18
|
+
|
|
19
|
+
_module_slug = "threats"
|
|
20
|
+
_exclude_graphql_fields = ["tenantsId"]
|
|
21
|
+
|
|
22
|
+
threatType: str # Required
|
|
23
|
+
status: Optional[str] = "Under Investigation" # Required
|
|
24
|
+
source: Optional[str] = "Open Source" # Required
|
|
25
|
+
title: Optional[str] = "" # Required
|
|
26
|
+
targetType: Optional[str] = "" # Required
|
|
27
|
+
threatOwnerId: Optional[str] = Field(default_factory=RegScaleModel.get_user_id) # Required
|
|
28
|
+
id: Optional[int] = 0
|
|
29
|
+
uuid: Optional[str] = None
|
|
30
|
+
investigationResults: Optional[str] = ""
|
|
31
|
+
notes: Optional[str] = ""
|
|
32
|
+
dateIdentified: str = Field(default_factory=get_current_datetime)
|
|
33
|
+
dateResolved: Optional[str] = ""
|
|
34
|
+
dateCreated: str = Field(default_factory=get_current_datetime)
|
|
35
|
+
description: Optional[str] = ""
|
|
36
|
+
targets: Optional[str] = ""
|
|
37
|
+
vulnerabilityAnalysis: Optional[str] = ""
|
|
38
|
+
mitigations: Optional[str] = ""
|
|
39
|
+
threatTypeUnintentional: Optional[bool] = True
|
|
40
|
+
threatTypePurposeful: Optional[bool] = True
|
|
41
|
+
threatTypeEnvironmental: Optional[bool] = True
|
|
42
|
+
threatTypeInsider: Optional[bool] = True
|
|
43
|
+
threatImpactConfidentiality: Optional[bool] = True
|
|
44
|
+
threatImpactIntegrity: Optional[bool] = True
|
|
45
|
+
threatImpactAvailability: Optional[bool] = True
|
|
46
|
+
investigated: Optional[bool] = True
|
|
47
|
+
exploitable: Optional[bool] = True
|
|
48
|
+
isPublic: Optional[bool] = True
|
|
49
|
+
facilityId: Optional[int] = None # This has to be None for default or else the server returns a 500 error
|
|
50
|
+
orgId: Optional[int] = None # This has to be None for default or else the server returns a 500 error
|
|
51
|
+
parentModule: Optional[str] = ""
|
|
52
|
+
parentId: Optional[int] = 0
|
|
53
|
+
tenantsId: Optional[int] = 1
|
|
54
|
+
|
|
55
|
+
@staticmethod
|
|
56
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
57
|
+
"""
|
|
58
|
+
Get additional endpoints for the Issues model.
|
|
59
|
+
|
|
60
|
+
:return: A dictionary of additional endpoints
|
|
61
|
+
:rtype: ConfigDict
|
|
62
|
+
"""
|
|
63
|
+
return ConfigDict(
|
|
64
|
+
get_count="/api/{model_slug}/count",
|
|
65
|
+
get_all_by_parent="/api/{model_slug}/getAllByParent/{intParentId}/{strModule}",
|
|
66
|
+
get_filtered_list="/api/{model_slug}/getFilteredList/{strFind}",
|
|
67
|
+
get_all_by_parent_module="/api/{model_slug}/getAllByParentModule/{strModule}",
|
|
68
|
+
graph="/api/{model_slug}/graph",
|
|
69
|
+
graph_by_date="/api/{model_slug}/graphByDate/{strGroupBy}/{year}",
|
|
70
|
+
filter_threats="/api/{model_slug}/filterThreats",
|
|
71
|
+
query_by_custom_field="/api/{model_slug}/queryByCustomField/{strFieldName}/{strValue}",
|
|
72
|
+
report="/api/{model_slug}/report/{strReport}",
|
|
73
|
+
schedule="/api/{model_slug}/schedule/{year}/{dvar}",
|
|
74
|
+
main_dashboard="/api/{model_slug}/mainDashboard/{intYear}",
|
|
75
|
+
main_dashboard_chart="/api/{model_slug}/mainDashboardChart/{year}",
|
|
76
|
+
dashboard="/api/{model_slug}/dashboard/{strGroupBy}",
|
|
77
|
+
dashboard_by_parent="/api/{model_slug}/dashboardByParent/{strGroupBy}/{intId}/{strModule}",
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
@staticmethod
|
|
81
|
+
def xstr(str_eval: Any) -> str:
|
|
82
|
+
"""
|
|
83
|
+
Replaces string with None value to ""
|
|
84
|
+
|
|
85
|
+
:param Any str_eval: key to replace None value to ""
|
|
86
|
+
:return: Updates provided str field to ""
|
|
87
|
+
:rtype: str
|
|
88
|
+
"""
|
|
89
|
+
return "" if str_eval is None else str_eval
|
|
90
|
+
|
|
91
|
+
@staticmethod
|
|
92
|
+
def bulk_insert(api: Optional[Api], threats: list[Union[dict, "Threat"]]) -> List["Threat"]:
|
|
93
|
+
"""
|
|
94
|
+
Bulk insert Threats to the RegScale API
|
|
95
|
+
|
|
96
|
+
:param Optional[Api] api: RegScale API
|
|
97
|
+
:param list[Union[dict, Threat]] threats: List of Threats to insert
|
|
98
|
+
:return: List of Threat objects from RegScale API
|
|
99
|
+
:rtype: List[Threat]
|
|
100
|
+
"""
|
|
101
|
+
if api:
|
|
102
|
+
import warnings
|
|
103
|
+
|
|
104
|
+
warnings.warn(
|
|
105
|
+
"Api parameter is deprecated and will be removed in future versions.",
|
|
106
|
+
DeprecationWarning,
|
|
107
|
+
stacklevel=2,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
results = []
|
|
111
|
+
threat_objects = []
|
|
112
|
+
for threat in threats:
|
|
113
|
+
if isinstance(threat, dict):
|
|
114
|
+
threat_objects.append(Threat(**threat))
|
|
115
|
+
else:
|
|
116
|
+
threat_objects.append(threat)
|
|
117
|
+
|
|
118
|
+
with ThreadPoolExecutor(max_workers=30) as executor:
|
|
119
|
+
futures = [
|
|
120
|
+
executor.submit(
|
|
121
|
+
threat.create,
|
|
122
|
+
)
|
|
123
|
+
for threat in threat_objects
|
|
124
|
+
]
|
|
125
|
+
for future in as_completed(futures):
|
|
126
|
+
results.append(future.result())
|
|
127
|
+
return results
|
|
128
|
+
|
|
129
|
+
@staticmethod
|
|
130
|
+
def bulk_update(api: Optional[Api], threats: list[Union[dict, "Threat"]]) -> List["Threat"]:
|
|
131
|
+
"""
|
|
132
|
+
Bulk insert Threats to the RegScale API
|
|
133
|
+
|
|
134
|
+
:param Optional[Api] api: RegScale API
|
|
135
|
+
:param list[Union[dict, Threat]] threats: List of Threats to update
|
|
136
|
+
:return: List of Threat objects from RegScale API
|
|
137
|
+
:rtype: List[Threat]
|
|
138
|
+
"""
|
|
139
|
+
if api:
|
|
140
|
+
import warnings
|
|
141
|
+
|
|
142
|
+
warnings.warn(
|
|
143
|
+
"Api parameter is deprecated and will be removed in future versions.",
|
|
144
|
+
DeprecationWarning,
|
|
145
|
+
stacklevel=2,
|
|
146
|
+
)
|
|
147
|
+
results = []
|
|
148
|
+
threat_objects = []
|
|
149
|
+
for threat in threats:
|
|
150
|
+
if isinstance(threat, dict):
|
|
151
|
+
threat_objects.append(Threat(**threat))
|
|
152
|
+
else:
|
|
153
|
+
threat_objects.append(threat)
|
|
154
|
+
|
|
155
|
+
# use threadpoolexecutor to speed up inserts
|
|
156
|
+
with ThreadPoolExecutor(max_workers=30) as executor:
|
|
157
|
+
futures = [
|
|
158
|
+
executor.submit(
|
|
159
|
+
threat.save,
|
|
160
|
+
)
|
|
161
|
+
for threat in threat_objects
|
|
162
|
+
]
|
|
163
|
+
for future in as_completed(futures):
|
|
164
|
+
results.append(future.result())
|
|
165
|
+
return results
|
|
166
|
+
|
|
167
|
+
@staticmethod
|
|
168
|
+
def fetch_all_threats() -> List["Threat"]:
|
|
169
|
+
"""
|
|
170
|
+
Find all Threats in RegScale
|
|
171
|
+
|
|
172
|
+
:return: List of Threats from RegScale
|
|
173
|
+
:rtype: List[Threat]
|
|
174
|
+
"""
|
|
175
|
+
from json import JSONDecodeError
|
|
176
|
+
|
|
177
|
+
api = Api()
|
|
178
|
+
body = f"""
|
|
179
|
+
query {{
|
|
180
|
+
threats(take: 50, skip: 0) {{
|
|
181
|
+
items {{
|
|
182
|
+
{Threat.build_graphql_fields()}
|
|
183
|
+
}}
|
|
184
|
+
pageInfo {{
|
|
185
|
+
hasNextPage
|
|
186
|
+
}}
|
|
187
|
+
,totalCount}}
|
|
188
|
+
}}
|
|
189
|
+
"""
|
|
190
|
+
try:
|
|
191
|
+
api.logger.info("Retrieving all threats from RegScale...")
|
|
192
|
+
existing_threats = api.graph(query=body)["threats"]["items"]
|
|
193
|
+
api.logger.info("Retrieved %i threat(s) from RegScale.", len(existing_threats))
|
|
194
|
+
except (JSONDecodeError, KeyError):
|
|
195
|
+
existing_threats = []
|
|
196
|
+
return [Threat(**threat) for threat in existing_threats]
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Dataclass for a RegScale User"""
|
|
4
|
+
|
|
5
|
+
# standard python imports
|
|
6
|
+
import random
|
|
7
|
+
import string
|
|
8
|
+
from typing import cast, Optional, List
|
|
9
|
+
|
|
10
|
+
from pydantic import Field, ConfigDict, field_validator
|
|
11
|
+
|
|
12
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
13
|
+
from .regscale_model import RegScaleModel, T
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def generate_password() -> str:
|
|
17
|
+
"""
|
|
18
|
+
Generates a random string that is 12-20 characters long
|
|
19
|
+
|
|
20
|
+
:return: random string 12-20 characters long
|
|
21
|
+
:rtype: str
|
|
22
|
+
"""
|
|
23
|
+
# select a random password length between 12-20 characters
|
|
24
|
+
length = random.randint(12, 20)
|
|
25
|
+
|
|
26
|
+
# get all possible strings to create a password
|
|
27
|
+
all_string_chars = string.ascii_lowercase + string.ascii_uppercase + string.digits + string.punctuation
|
|
28
|
+
|
|
29
|
+
# randomly select characters matching the random length
|
|
30
|
+
temp = random.sample(all_string_chars, length)
|
|
31
|
+
# return a string from the temp list of samples
|
|
32
|
+
return "".join(temp)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class User(RegScaleModel):
|
|
36
|
+
"""User Model"""
|
|
37
|
+
|
|
38
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
39
|
+
_module_slug = "accounts"
|
|
40
|
+
_unique_fields = [
|
|
41
|
+
["userName", "email"],
|
|
42
|
+
]
|
|
43
|
+
_exclude_graphql_fields = ["extra_data", "tenantsId", "password"]
|
|
44
|
+
|
|
45
|
+
userName: str = Field(alias="username")
|
|
46
|
+
email: Optional[str] = None
|
|
47
|
+
firstName: Optional[str] = None
|
|
48
|
+
lastName: Optional[str] = None
|
|
49
|
+
tenantId: int = 1
|
|
50
|
+
initials: Optional[str] = None
|
|
51
|
+
id: Optional[str] = None
|
|
52
|
+
password: str = Field(default_factory=generate_password)
|
|
53
|
+
homePageUrl: Optional[str] = "/workbench"
|
|
54
|
+
name: Optional[str] = None
|
|
55
|
+
workPhone: Optional[str] = None
|
|
56
|
+
mobilePhone: Optional[str] = None
|
|
57
|
+
avatar: Optional[bytes] = None
|
|
58
|
+
jobTitle: Optional[str] = None
|
|
59
|
+
orgId: Optional[int] = None
|
|
60
|
+
pictureURL: Optional[str] = None
|
|
61
|
+
activated: bool = False
|
|
62
|
+
emailNotifications: bool = True
|
|
63
|
+
ldapUser: bool = False
|
|
64
|
+
externalId: Optional[str] = None
|
|
65
|
+
dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
66
|
+
lastLogin: Optional[str] = None
|
|
67
|
+
readOnly: bool = True
|
|
68
|
+
roles: Optional[List[str]] = None
|
|
69
|
+
|
|
70
|
+
@field_validator("homePageUrl")
|
|
71
|
+
def validate_regscale_version_and_home_page_url(cls, v: str) -> Optional[str]:
|
|
72
|
+
"""
|
|
73
|
+
Validate the RegScale version and if it is compatible with homePageUrl, has to be >=6.13
|
|
74
|
+
|
|
75
|
+
:param str v: homePageUrl value
|
|
76
|
+
:return: The homePageUrl if the RegScale version is compatible, None otherwise
|
|
77
|
+
"""
|
|
78
|
+
from packaging.version import Version
|
|
79
|
+
|
|
80
|
+
regscale_version = cls._get_api_handler().regscale_version
|
|
81
|
+
|
|
82
|
+
if len(regscale_version) >= 10 or Version(regscale_version) >= Version("6.14.0.0"):
|
|
83
|
+
return v
|
|
84
|
+
else:
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def _get_additional_endpoints(cls) -> ConfigDict:
|
|
89
|
+
"""
|
|
90
|
+
Get additional endpoints for the Accounts model, using {model_slug} as a placeholder for the model slug.
|
|
91
|
+
|
|
92
|
+
:return: A dictionary of additional endpoints
|
|
93
|
+
:rtype: ConfigDict
|
|
94
|
+
"""
|
|
95
|
+
return ConfigDict(
|
|
96
|
+
get_all="/api/{model_slug}",
|
|
97
|
+
create_account=cls._module_slug_url,
|
|
98
|
+
update_account=cls._module_slug_url,
|
|
99
|
+
get_accounts=cls._module_slug_url,
|
|
100
|
+
register_questionnaire_user="/api/{model_slug}/registerQuestionnaireUser",
|
|
101
|
+
cache_reset="/api/{model_slug}/cacheReset",
|
|
102
|
+
create_ldap_accounts="/api/{model_slug}/ldap",
|
|
103
|
+
create_azuread_accounts="/api/{model_slug}/azureAD",
|
|
104
|
+
assign_role="/api/{model_slug}/assignRole",
|
|
105
|
+
check_role="/api/{model_slug}/checkRole/{strUserId}/{strRoleId}",
|
|
106
|
+
delete_role="/api/{model_slug}/deleteRole/{strUserId}/{strRoleId}",
|
|
107
|
+
get_my_manager="/api/{model_slug}/getMyManager",
|
|
108
|
+
get_manager_by_user_id="/api/{model_slug}/getManagerByUserId/{strUserId}",
|
|
109
|
+
list="/api/{model_slug}/getList",
|
|
110
|
+
get_inactive_users="/api/{model_slug}/getInactiveUsers",
|
|
111
|
+
get_accounts_by_tenant="/api/{model_slug}/{tenantId}",
|
|
112
|
+
get_accounts_by_email_flag="/api/{model_slug}/{intTenantId}/{bEmailFlag}",
|
|
113
|
+
get_all_by_tenant="/api/{model_slug}/getAllByTenant/{intTenantId}",
|
|
114
|
+
filter_users="/api/{model_slug}/filterUsers/{intTenant}/{strSearch}/{bActive}/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
|
|
115
|
+
filter_user_roles="/api/{model_slug}/filterUserRoles/{intId}/{strRole}/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
|
|
116
|
+
change_user_status="/api/{model_slug}/changeUserStatus/{strId}/{bStatus}",
|
|
117
|
+
get_user_by_username="/api/{model_slug}/getUserByUsername/{strUsername}",
|
|
118
|
+
get="/api/{model_slug}/find/{id}",
|
|
119
|
+
get_roles="/api/{model_slug}/getRoles",
|
|
120
|
+
get_roles_by_user="/api/{model_slug}/getRolesByUser/{strUser}",
|
|
121
|
+
is_delegate="/api/{model_slug}/isDelegate/{strUser}",
|
|
122
|
+
get_delegates="/api/{model_slug}/getDelegates/{userId}",
|
|
123
|
+
change_avatar="/api/{model_slug}/changeAvatar/{strUsername}",
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
@classmethod
|
|
127
|
+
def get_tenant_id_for_user_id(cls, user_id: str) -> Optional[int]:
|
|
128
|
+
"""
|
|
129
|
+
Retrieve all users by tenant ID.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
user_id: str : user id to find
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Optional[int]: optionals
|
|
136
|
+
"""
|
|
137
|
+
user = cls.get_user_by_id(user_id)
|
|
138
|
+
return user.tenantId if user else None
|
|
139
|
+
|
|
140
|
+
@classmethod
|
|
141
|
+
def get_user_by_id(cls, user_id: str) -> "User":
|
|
142
|
+
"""
|
|
143
|
+
Get a user by their ID
|
|
144
|
+
|
|
145
|
+
:param str user_id: The user's ID
|
|
146
|
+
:return: The user object
|
|
147
|
+
:rtype: User
|
|
148
|
+
"""
|
|
149
|
+
response = cls._get_api_handler().get(
|
|
150
|
+
endpoint=cls.get_endpoint("get").format(model_slug=cls._module_slug, id=user_id)
|
|
151
|
+
)
|
|
152
|
+
return cls._handle_response(response)
|
|
153
|
+
|
|
154
|
+
@classmethod
|
|
155
|
+
def get_all(cls) -> List["User"]:
|
|
156
|
+
"""
|
|
157
|
+
Get all users from RegScale
|
|
158
|
+
|
|
159
|
+
:return: List of RegScale users
|
|
160
|
+
:rtype: List[User]
|
|
161
|
+
"""
|
|
162
|
+
response = cls._get_api_handler().get(endpoint=cls.get_endpoint("get_all"))
|
|
163
|
+
return cast(List[T], cls._handle_list_response(response))
|
|
164
|
+
|
|
165
|
+
def assign_role(self, role_id: str) -> bool:
|
|
166
|
+
"""
|
|
167
|
+
Assign a role to a user
|
|
168
|
+
|
|
169
|
+
:return: Whether the role was assigned
|
|
170
|
+
:rtype: bool
|
|
171
|
+
"""
|
|
172
|
+
response = self._get_api_handler().post(
|
|
173
|
+
data={"roleId": role_id, "userId": self.id}, endpoint=self.get_endpoint("assign_role")
|
|
174
|
+
)
|
|
175
|
+
return response.ok
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""
|
|
2
|
+
UserGroup model for the RegScale API.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from pydantic import ConfigDict, Field
|
|
8
|
+
|
|
9
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
10
|
+
from regscale.models import RegScaleModel
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class UserGroup(RegScaleModel):
|
|
14
|
+
_module_slug = "userGroups"
|
|
15
|
+
|
|
16
|
+
id: Optional[int] = None
|
|
17
|
+
groupsId: int
|
|
18
|
+
userId: str
|
|
19
|
+
isPublic: Optional[bool] = True
|
|
20
|
+
tenantsId: Optional[int] = 1
|
|
21
|
+
createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
22
|
+
dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
23
|
+
lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
24
|
+
dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
25
|
+
|
|
26
|
+
@staticmethod
|
|
27
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
28
|
+
"""
|
|
29
|
+
Get additional endpoints for the UserGroup model.
|
|
30
|
+
|
|
31
|
+
:return: A dictionary of additional endpoints
|
|
32
|
+
:rtype: ConfigDict
|
|
33
|
+
"""
|
|
34
|
+
return ConfigDict(
|
|
35
|
+
filter_user_groups="/api/{model_slug}/filterUserGroups/{intGroupId}/{intPage}/{intPageSize}",
|
|
36
|
+
# Get the list of users in the specified group (GET)
|
|
37
|
+
get_users_by_group="/api/userGroups/getUsersByGroup/{intGroupId}",
|
|
38
|
+
# Get the list of groups for a given user (GET)
|
|
39
|
+
get_groups_by_user="/api/userGroups/getGroupsByUser/{strUserId}",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def get_users_by_group(cls, group_id: int):
|
|
44
|
+
"""
|
|
45
|
+
Get the list of users in the specified group.
|
|
46
|
+
|
|
47
|
+
:param group_id: The group ID
|
|
48
|
+
:return: A list of users
|
|
49
|
+
"""
|
|
50
|
+
response = cls._get_api_handler().get(
|
|
51
|
+
endpoint=cls.get_endpoint("get_users_by_group").format(intGroupId=group_id)
|
|
52
|
+
)
|
|
53
|
+
if response and response.ok:
|
|
54
|
+
return response.json()
|
|
55
|
+
return []
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Model for Vulnerability in the application"""
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import List, Optional, Union
|
|
6
|
+
from urllib.parse import urljoin
|
|
7
|
+
from warnings import warn
|
|
8
|
+
|
|
9
|
+
from pydantic import ConfigDict, Field
|
|
10
|
+
from requests import Response
|
|
11
|
+
|
|
12
|
+
from regscale.core.app.api import Api
|
|
13
|
+
from regscale.core.app.application import Application
|
|
14
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
15
|
+
from regscale.models import regscale_models
|
|
16
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def deprecated(message):
|
|
20
|
+
def decorator(func):
|
|
21
|
+
def wrapper(*args, **kwargs):
|
|
22
|
+
warn(f"{func.__name__} is deprecated. {message}", DeprecationWarning, stacklevel=2)
|
|
23
|
+
return func(*args, **kwargs)
|
|
24
|
+
|
|
25
|
+
return wrapper
|
|
26
|
+
|
|
27
|
+
return decorator
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class VulnerabilitySeverity(str, Enum):
|
|
31
|
+
"""Vulnerability Severity"""
|
|
32
|
+
|
|
33
|
+
Low = "LOW"
|
|
34
|
+
Medium = "MEDIUM"
|
|
35
|
+
High = "HIGH"
|
|
36
|
+
Critical = "CRITICAL"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class VulnerabilityStatus(str, Enum):
|
|
40
|
+
"""Vulnerability Status"""
|
|
41
|
+
|
|
42
|
+
Open = "OPEN"
|
|
43
|
+
Closed = "CLOSED"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Vulnerability(RegScaleModel):
|
|
47
|
+
"""Vulnerability Model"""
|
|
48
|
+
|
|
49
|
+
_module_slug = "vulnerability"
|
|
50
|
+
_unique_fields = [
|
|
51
|
+
["plugInName", "parentId", "parentModule"],
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
id: int = 0
|
|
55
|
+
createdById: str = Field(default_factory=RegScaleModel.get_user_id)
|
|
56
|
+
dateCreated: str = Field(default_factory=get_current_datetime)
|
|
57
|
+
lastUpdatedById: str = Field(default_factory=RegScaleModel.get_user_id)
|
|
58
|
+
dateLastUpdated: str = Field(default_factory=get_current_datetime)
|
|
59
|
+
uuid: Optional[str] = None
|
|
60
|
+
scanId: Optional[int] = None
|
|
61
|
+
parentId: Optional[int] = None
|
|
62
|
+
parentModule: Optional[str] = None
|
|
63
|
+
lastSeen: Optional[str] = None
|
|
64
|
+
firstSeen: Optional[str] = None
|
|
65
|
+
daysOpen: Optional[int] = None
|
|
66
|
+
dns: Optional[str] = None
|
|
67
|
+
ipAddress: Optional[str] = Field(default="")
|
|
68
|
+
mitigated: Optional[bool] = None
|
|
69
|
+
operatingSystem: Optional[str] = None
|
|
70
|
+
port: Optional[Union[str, int]] = None
|
|
71
|
+
protocol: Optional[str] = None
|
|
72
|
+
severity: Optional[Union[str, VulnerabilitySeverity]] = None
|
|
73
|
+
plugInName: Optional[str] = None
|
|
74
|
+
plugInId: Optional[int] = None
|
|
75
|
+
cve: Optional[str] = None
|
|
76
|
+
vprScore: Optional[Union[int, float]] = None
|
|
77
|
+
exploitAvailable: Optional[bool] = None
|
|
78
|
+
title: Optional[str] = None
|
|
79
|
+
cvsSv3BaseScore: Optional[Union[float, int]] = None
|
|
80
|
+
description: Optional[str] = None
|
|
81
|
+
plugInText: Optional[str] = None
|
|
82
|
+
tenantsId: int = Field(default=0)
|
|
83
|
+
isPublic: bool = Field(default=False)
|
|
84
|
+
dateClosed: Optional[str] = None
|
|
85
|
+
status: Optional[VulnerabilityStatus] = VulnerabilityStatus.Open
|
|
86
|
+
|
|
87
|
+
def __eq__(self, other) -> bool:
|
|
88
|
+
"""
|
|
89
|
+
Check if two Vulnerability objects are equal is needed for comparison operations in flat file importer
|
|
90
|
+
:param other:
|
|
91
|
+
:return: True if the two objects are equal, False otherwise
|
|
92
|
+
:rtype: bool
|
|
93
|
+
"""
|
|
94
|
+
if not isinstance(other, Vulnerability):
|
|
95
|
+
return False
|
|
96
|
+
return (
|
|
97
|
+
self.plugInName == other.plugInName
|
|
98
|
+
and self.parentId == other.parentId
|
|
99
|
+
and self.parentModule == other.parentModule
|
|
100
|
+
and self.ipAddress == other.ipAddress
|
|
101
|
+
and self.dns == other.dns
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
def __init__(self, **data):
|
|
105
|
+
# Map snake_case to camelCase before initialization
|
|
106
|
+
field_mappings = {
|
|
107
|
+
"scan_id": "scanId",
|
|
108
|
+
"parent_id": "parentId",
|
|
109
|
+
"parent_module": "parentModule",
|
|
110
|
+
"last_seen": "lastSeen",
|
|
111
|
+
"first_seen": "firstSeen",
|
|
112
|
+
"days_open": "daysOpen",
|
|
113
|
+
"ip_address": "ipAddress",
|
|
114
|
+
"operating_system": "operatingSystem",
|
|
115
|
+
"plugin_name": "plugInName",
|
|
116
|
+
"plugin_id": "plugInId",
|
|
117
|
+
"vpr_score": "vprScore",
|
|
118
|
+
"exploit_available": "exploitAvailable",
|
|
119
|
+
"cvss_v3_base_score": "cvsSv3BaseScore",
|
|
120
|
+
"plugin_text": "plugInText",
|
|
121
|
+
"tenants_id": "tenantsId",
|
|
122
|
+
"is_public": "isPublic",
|
|
123
|
+
"date_closed": "dateClosed",
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# Convert snake_case keys to camelCase
|
|
127
|
+
for snake_key, camel_key in field_mappings.items():
|
|
128
|
+
if snake_key in data:
|
|
129
|
+
data[camel_key] = data.pop(snake_key)
|
|
130
|
+
|
|
131
|
+
super().__init__(**data)
|
|
132
|
+
|
|
133
|
+
@staticmethod
|
|
134
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
135
|
+
"""
|
|
136
|
+
Get additional endpoints for the Vulnerability model, using {model_slug} as a placeholder for the model slug.
|
|
137
|
+
|
|
138
|
+
:return: A dictionary of additional endpoints
|
|
139
|
+
:rtype: ConfigDict
|
|
140
|
+
"""
|
|
141
|
+
return ConfigDict( # type: ignore
|
|
142
|
+
get_count="/api/{model_slug}/getCount", # type: ignore
|
|
143
|
+
batch_create="/api/{model_slug}/batchCreate", # type: ignore
|
|
144
|
+
find_by_guid="/api/{model_slug}/findByGUID/{strGUID}", # type: ignore
|
|
145
|
+
drilldown="/api/{model_slug}/drilldown/{parentId}/{scanId}/{strSeverity}/{intPage}/" # type: ignore
|
|
146
|
+
"{intPageSize}",
|
|
147
|
+
lookup_cve="/api/{model_slug}/lookupCVE/{strCVE}", # type: ignore
|
|
148
|
+
get="/api/{model_slug}/find/{id}", # type: ignore
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
@staticmethod
|
|
152
|
+
def determine_cvss3_severity_text(cvss_v3_base_score: float) -> str:
|
|
153
|
+
"""
|
|
154
|
+
Determine CVSS3 Severity Text from CVSS3 Base Score
|
|
155
|
+
|
|
156
|
+
:param float cvss_v3_base_score: CVSS3 Base Score
|
|
157
|
+
:return: CVSS3 Severity Text
|
|
158
|
+
:rtype: str
|
|
159
|
+
"""
|
|
160
|
+
results = "low"
|
|
161
|
+
if 4.0 <= cvss_v3_base_score <= 6.9:
|
|
162
|
+
results = "medium"
|
|
163
|
+
elif 7.0 <= cvss_v3_base_score <= 8.9:
|
|
164
|
+
results = "high"
|
|
165
|
+
elif cvss_v3_base_score > 8.9:
|
|
166
|
+
results = "critical"
|
|
167
|
+
return results
|
|
168
|
+
|
|
169
|
+
@staticmethod
|
|
170
|
+
@deprecated("Use Vulnerability.get_all_by_parent() instead")
|
|
171
|
+
def find_vulns_by_scan(app: Application, scan_id: int) -> List["Vulnerability"]: # noqa: F841
|
|
172
|
+
"""
|
|
173
|
+
Find Vulnerabilities by Scan ID
|
|
174
|
+
|
|
175
|
+
:param Application app: Application instance
|
|
176
|
+
:param int scan_id: Scan ID
|
|
177
|
+
:return: List of Vulnerabilities
|
|
178
|
+
:rtype: List[Vulnerability]
|
|
179
|
+
"""
|
|
180
|
+
return Vulnerability.get_all_by_parent(parent_id=scan_id, parent_module=regscale_models.Scan.get_module_slug())
|
|
181
|
+
|
|
182
|
+
@classmethod
|
|
183
|
+
@deprecated("Use Vulnerability.create() instead")
|
|
184
|
+
def post_vulnerability(cls, vulnerability: "Vulnerability") -> Optional["Vulnerability"]:
|
|
185
|
+
"""
|
|
186
|
+
Post a vulnerability to the API
|
|
187
|
+
|
|
188
|
+
:param Vulnerability vulnerability: The vulnerability to be posted
|
|
189
|
+
:return: The response from the API as a dictionary
|
|
190
|
+
:rtype: Optional["Vulnerability"]
|
|
191
|
+
"""
|
|
192
|
+
return vulnerability.create()
|
|
193
|
+
|
|
194
|
+
@classmethod
|
|
195
|
+
@deprecated(
|
|
196
|
+
"Use Vulnerability.create() for individual vulnerabilities or Vulnerability.batch_create() for "
|
|
197
|
+
"multiple vulnerabilities"
|
|
198
|
+
)
|
|
199
|
+
def post_vulnerabilities(
|
|
200
|
+
cls,
|
|
201
|
+
app: Application, # noqa: F841
|
|
202
|
+
vulnerabilities: List["Vulnerability"],
|
|
203
|
+
output_to_console: Optional[bool] = True,
|
|
204
|
+
) -> List[Response]:
|
|
205
|
+
"""
|
|
206
|
+
Insert new vulnerabilities into RegScale
|
|
207
|
+
|
|
208
|
+
:param Application app: Application object
|
|
209
|
+
:param List[Vulnerability] vulnerabilities: List of Vulnerability objects
|
|
210
|
+
:param Optional[bool] output_to_console: Whether to output to console, defaults to True
|
|
211
|
+
:return: A list of Responses
|
|
212
|
+
:rtype List[Response]
|
|
213
|
+
"""
|
|
214
|
+
responses = []
|
|
215
|
+
|
|
216
|
+
def batch_post(url: str, dat: list[dict]) -> Response:
|
|
217
|
+
"""
|
|
218
|
+
Simple wrapper to post a list of JSON data to a URL
|
|
219
|
+
|
|
220
|
+
:param str url: URL to post to
|
|
221
|
+
:param list[dict] dat: A list of JSON data to post
|
|
222
|
+
:return: Response object
|
|
223
|
+
:rtype: Response
|
|
224
|
+
"""
|
|
225
|
+
return api.post(url=url, json=dat)
|
|
226
|
+
|
|
227
|
+
api = Api()
|
|
228
|
+
if output_to_console and vulnerabilities:
|
|
229
|
+
api.logger.info("Creating %i new vulnerabilities in RegScale...", len(vulnerabilities))
|
|
230
|
+
# Create batches of vulnerabilities to post
|
|
231
|
+
batch_size = 500
|
|
232
|
+
batches = [vulnerabilities[i : i + batch_size] for i in range(0, len(vulnerabilities), batch_size)]
|
|
233
|
+
for batch in batches:
|
|
234
|
+
res = batch_post(
|
|
235
|
+
url=urljoin(api.config["domain"], cls.get_endpoint("batch_create")),
|
|
236
|
+
dat=[vuln.model_dump() for vuln in batch],
|
|
237
|
+
)
|
|
238
|
+
if res.ok:
|
|
239
|
+
responses.extend(res.json())
|
|
240
|
+
if len(responses):
|
|
241
|
+
api.logger.info("Successfully created %i new vulnerabilities in RegScale", len(responses))
|
|
242
|
+
return responses
|