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,190 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Optional, List, Dict
|
|
3
|
+
|
|
4
|
+
from pydantic import ConfigDict, Field
|
|
5
|
+
|
|
6
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
7
|
+
from regscale.models.regscale_models.search import Search
|
|
8
|
+
from regscale.models.regscale_models import Asset
|
|
9
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
10
|
+
from regscale.models.regscale_models.regscale_model import T
|
|
11
|
+
from regscale.models.regscale_models.mixins.parent_cache import PlanCacheMixin
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AssetMapping(RegScaleModel, PlanCacheMixin["AssetMapping"]):
|
|
17
|
+
"""
|
|
18
|
+
AssetMapping model class.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
_module_slug = "assetmapping"
|
|
22
|
+
_unique_fields = [
|
|
23
|
+
["componentId", "assetId"],
|
|
24
|
+
]
|
|
25
|
+
_parent_id_field = "componentId"
|
|
26
|
+
|
|
27
|
+
# New class attributes
|
|
28
|
+
_graph_query_name = "assetMappings"
|
|
29
|
+
_graph_plan_id_path = "component.securityPlansId"
|
|
30
|
+
|
|
31
|
+
id: Optional[int] = 0
|
|
32
|
+
uuid: Optional[str] = None
|
|
33
|
+
assetId: int
|
|
34
|
+
componentId: int
|
|
35
|
+
createdById: Optional[str] = None
|
|
36
|
+
dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
37
|
+
lastUpdatedById: Optional[str] = None
|
|
38
|
+
isPublic: Optional[bool] = True
|
|
39
|
+
dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
40
|
+
tenantsId: Optional[int] = 1
|
|
41
|
+
|
|
42
|
+
@staticmethod
|
|
43
|
+
def get_assets(component_id: int) -> List[T]:
|
|
44
|
+
"""
|
|
45
|
+
Get assets for a given component ID.
|
|
46
|
+
|
|
47
|
+
:param int component_id: The ID of the component
|
|
48
|
+
:return: A list of assets
|
|
49
|
+
:rtype: List[T]
|
|
50
|
+
"""
|
|
51
|
+
asset_mappings = AssetMapping.find_mappings(component_id=component_id)
|
|
52
|
+
assets = []
|
|
53
|
+
for asset_mapping in asset_mappings:
|
|
54
|
+
assets.append(Asset.get_object(object_id=asset_mapping.assetId))
|
|
55
|
+
return assets
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
59
|
+
"""
|
|
60
|
+
Get additional endpoints for the AssetMapping model.
|
|
61
|
+
|
|
62
|
+
:return: A dictionary of additional endpoints
|
|
63
|
+
:rtype: ConfigDict
|
|
64
|
+
"""
|
|
65
|
+
return ConfigDict(
|
|
66
|
+
get_all_by_parent="/api/{model_slug}/getMappingsAsComponents/{intParentID}",
|
|
67
|
+
filter_asset_mappings="/api/{model_slug}/filterAssetMappings/{intAsset}/{intComp}/{strSearch}/{intPage}/{intPageSize}",
|
|
68
|
+
find_mappings="/api/{model_slug}/findMappings/{intId}",
|
|
69
|
+
get_mappings_as_components="/api/{model_slug}/getMappingsAsComponents/{intId}",
|
|
70
|
+
get_mappings_as_assets="/api/{model_slug}/getMappingsAsAssets/{intId}/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
@classmethod
|
|
74
|
+
def cast_list_object(
|
|
75
|
+
cls,
|
|
76
|
+
item: Dict,
|
|
77
|
+
parent_id: Optional[int] = None,
|
|
78
|
+
parent_module: Optional[str] = None,
|
|
79
|
+
) -> "AssetMapping":
|
|
80
|
+
"""
|
|
81
|
+
Cast list of items to class instances.
|
|
82
|
+
|
|
83
|
+
:param Dict item: item to cast
|
|
84
|
+
:param Optional[int] parent_id: Parent ID, defaults to None
|
|
85
|
+
:param Optional[str] parent_module: Parent module, defaults to None
|
|
86
|
+
:return: Class instance created from the item
|
|
87
|
+
:rtype: "AssetMapping"
|
|
88
|
+
"""
|
|
89
|
+
item["assetId"] = parent_id or item.get("assetId")
|
|
90
|
+
return cls(**item)
|
|
91
|
+
|
|
92
|
+
@classmethod
|
|
93
|
+
def get_all_by_parent(
|
|
94
|
+
cls,
|
|
95
|
+
parent_id: int,
|
|
96
|
+
parent_module: Optional[str] = None,
|
|
97
|
+
search: Optional[Search] = None,
|
|
98
|
+
) -> List[T]:
|
|
99
|
+
"""
|
|
100
|
+
Retrieves all asset mappings for a given parent ID and ONLY Components.
|
|
101
|
+
|
|
102
|
+
:param int parent_id: The ID of the parent
|
|
103
|
+
:param Optional[str] parent_module: The module of the parent
|
|
104
|
+
:param Optional[Search] search: The search object, defaults to None
|
|
105
|
+
:return: A list of asset mappings
|
|
106
|
+
:rtype: List[T]
|
|
107
|
+
:returns: A list of asset mappings for the given parent ID
|
|
108
|
+
"""
|
|
109
|
+
return cls.find_mappings(parent_id)
|
|
110
|
+
|
|
111
|
+
@classmethod
|
|
112
|
+
def find_mappings(cls, component_id: int) -> List[T]:
|
|
113
|
+
"""
|
|
114
|
+
Retrieves all component mappings for a given component ID.
|
|
115
|
+
|
|
116
|
+
:param int component_id: The ID of the component
|
|
117
|
+
:return: A list of component mappings
|
|
118
|
+
:rtype: List[T]
|
|
119
|
+
"""
|
|
120
|
+
cache_key = f"{component_id}:{cls.__name__}"
|
|
121
|
+
|
|
122
|
+
# Get the lock for this cache_key
|
|
123
|
+
lock = cls._get_lock(cache_key)
|
|
124
|
+
|
|
125
|
+
with lock:
|
|
126
|
+
# Check the cache
|
|
127
|
+
cached_mappings = cls._parent_cache.get(cache_key)
|
|
128
|
+
if cached_mappings is not None:
|
|
129
|
+
return cached_mappings
|
|
130
|
+
|
|
131
|
+
# Not cached, make the API call
|
|
132
|
+
response = cls._get_api_handler().get(
|
|
133
|
+
endpoint=cls.get_endpoint("find_mappings").format(model_slug=cls.get_module_slug(), intId=component_id)
|
|
134
|
+
)
|
|
135
|
+
mappings = cls._handle_list_response(response)
|
|
136
|
+
|
|
137
|
+
# Cache the mappings
|
|
138
|
+
cls.cache_list_objects(cache_key=cache_key, objects=mappings)
|
|
139
|
+
|
|
140
|
+
return mappings
|
|
141
|
+
|
|
142
|
+
@classmethod
|
|
143
|
+
def get_mappings_as_components(cls, asset_id: int) -> Optional[List[T]]:
|
|
144
|
+
"""
|
|
145
|
+
Retrieves all component mappings for a given asset ID.
|
|
146
|
+
|
|
147
|
+
:param int asset_id: The ID of the asset
|
|
148
|
+
:return: A list of component mappings or None
|
|
149
|
+
:rtype: Optional[List[T]]
|
|
150
|
+
"""
|
|
151
|
+
response = cls._get_api_handler().get(
|
|
152
|
+
endpoint=cls.get_endpoint("get_mappings_as_components").format(
|
|
153
|
+
model_slug=cls.get_module_slug(), intId=asset_id
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
if not response or response.status_code in [204, 404]:
|
|
157
|
+
return None
|
|
158
|
+
if response.ok:
|
|
159
|
+
return [cls(**item) for item in response.json()]
|
|
160
|
+
return None
|
|
161
|
+
|
|
162
|
+
def get_mappings_as_assets(
|
|
163
|
+
self, component_id: int, sort_by: str, direction: str, page: int, page_size: int
|
|
164
|
+
) -> Optional[List["AssetMapping"]]:
|
|
165
|
+
"""
|
|
166
|
+
Retrieves all asset mappings for a given component ID.
|
|
167
|
+
|
|
168
|
+
:param int component_id: The ID of the component
|
|
169
|
+
:param str sort_by: The field to sort by
|
|
170
|
+
:param str direction: The direction of sorting ('asc' or 'desc')
|
|
171
|
+
:param int page: The page number for pagination
|
|
172
|
+
:param int page_size: The number of items per page
|
|
173
|
+
:return: A list of asset mappings or None
|
|
174
|
+
:rtype: Optional[List[AssetMapping]]
|
|
175
|
+
"""
|
|
176
|
+
response = self._get_api_handler().get(
|
|
177
|
+
endpoint=self.get_endpoint("get_mappings_as_assets").format(
|
|
178
|
+
model_slug=self._module_slug,
|
|
179
|
+
intId=component_id,
|
|
180
|
+
strSortBy=sort_by,
|
|
181
|
+
strDirection=direction,
|
|
182
|
+
intPage=page,
|
|
183
|
+
intPageSize=page_size,
|
|
184
|
+
)
|
|
185
|
+
)
|
|
186
|
+
if not response or response.status_code in [204, 404]:
|
|
187
|
+
return None
|
|
188
|
+
if response.ok:
|
|
189
|
+
return [self.__class__(**item) for item in response.json()]
|
|
190
|
+
return None
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from pydantic import Field
|
|
5
|
+
|
|
6
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
7
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CaseStatus(str, Enum):
|
|
11
|
+
"""
|
|
12
|
+
Enum for the CaseStatus field in the Case model.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
in_progress = "In Progress"
|
|
16
|
+
closed = "Closed"
|
|
17
|
+
pending = "Pending"
|
|
18
|
+
resolved = "Resolved"
|
|
19
|
+
complete = "Complete"
|
|
20
|
+
cancelled = "Cancelled"
|
|
21
|
+
on_hold = "On Hold"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Case(RegScaleModel):
|
|
25
|
+
_module_slug = "cases"
|
|
26
|
+
_module_id = 28
|
|
27
|
+
|
|
28
|
+
id: Optional[int] = None
|
|
29
|
+
title: str
|
|
30
|
+
uuid: Optional[str] = None
|
|
31
|
+
description: Optional[str] = None
|
|
32
|
+
status: str = CaseStatus.pending
|
|
33
|
+
caseNumber: Optional[str] = None
|
|
34
|
+
caseWorkerId: str = Field(default_factory=RegScaleModel.get_user_id)
|
|
35
|
+
dateReported: str = Field(default_factory=get_current_datetime)
|
|
36
|
+
dateResolved: Optional[str] = None
|
|
37
|
+
notes: Optional[str] = None
|
|
38
|
+
reportedBy: str = Field(default_factory=RegScaleModel.get_user_id)
|
|
39
|
+
facilityId: Optional[int] = None
|
|
40
|
+
orgId: Optional[int] = None
|
|
41
|
+
parentId: Optional[int] = None
|
|
42
|
+
parentModule: Optional[str] = None
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Model for Catalog in the application"""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import io
|
|
7
|
+
import json
|
|
8
|
+
import warnings
|
|
9
|
+
from typing import List, Optional, Union
|
|
10
|
+
from urllib.parse import urljoin
|
|
11
|
+
|
|
12
|
+
from pydantic import ConfigDict
|
|
13
|
+
from requests import Response
|
|
14
|
+
|
|
15
|
+
from regscale.core.app.api import Api
|
|
16
|
+
from regscale.core.app.application import Application
|
|
17
|
+
from regscale.core.app.utils.api_handler import APIRetrieveError
|
|
18
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
19
|
+
from regscale.models.regscale_models.security_control import SecurityControl
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Catalog(RegScaleModel):
|
|
23
|
+
"""Catalog class"""
|
|
24
|
+
|
|
25
|
+
_module_slug = "catalogues"
|
|
26
|
+
|
|
27
|
+
id: int = 0
|
|
28
|
+
abstract: Optional[str] = None
|
|
29
|
+
datePublished: Optional[str] = None
|
|
30
|
+
description: Optional[str] = None
|
|
31
|
+
keywords: Optional[str] = None
|
|
32
|
+
lastRevisionDate: Optional[str] = None
|
|
33
|
+
title: str = ""
|
|
34
|
+
url: Optional[str] = None
|
|
35
|
+
tenantsId: Optional[int] = None
|
|
36
|
+
uuid: Optional[str] = None
|
|
37
|
+
createdById: Optional[str] = None
|
|
38
|
+
dateCreated: Optional[str] = None
|
|
39
|
+
dateLastUpdated: Optional[str] = None
|
|
40
|
+
lastUpdatedById: Optional[str] = None
|
|
41
|
+
master: bool = False
|
|
42
|
+
sourceOscalURL: Optional[str] = None
|
|
43
|
+
archived: bool = False
|
|
44
|
+
isPublic: bool = True
|
|
45
|
+
securityControls: List[SecurityControl] = []
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
49
|
+
"""
|
|
50
|
+
Get additional endpoints for the Catalogues model
|
|
51
|
+
|
|
52
|
+
:return: A dictionary of additional endpoints
|
|
53
|
+
:rtype: ConfigDict
|
|
54
|
+
"""
|
|
55
|
+
return ConfigDict( # type: ignore
|
|
56
|
+
get_count="/api/{model_slug}/getCount",
|
|
57
|
+
get_list="/api/{model_slug}/getList",
|
|
58
|
+
get_catalog_with_all_details="/api/{model_slug}/getCatalogWithAllDetails/{intID}",
|
|
59
|
+
filter_catalogues="/api/{model_slug}/filterCatalogues",
|
|
60
|
+
graph="/api/{model_slug}/graph",
|
|
61
|
+
convert_mappings="/api/{model_slug}/convertMappings/{intID}",
|
|
62
|
+
find_by_guid="/api/{model_slug}/findByGUID/{strID}",
|
|
63
|
+
get_titles="/api/{model_slug}/getTitles",
|
|
64
|
+
get_nist="/api/{model_slug}/getNIST",
|
|
65
|
+
get_updatable="/api/{model_slug}/getUpdatableCatalogs",
|
|
66
|
+
compare_and_update="/api/{model_slug}/compareAndUpdate/{intID}",
|
|
67
|
+
update_regscale_catalog="/api/{model_slug}/updateRegScaleCatalog/{intID}",
|
|
68
|
+
get_update_report_for_catalog="/api/{model_slug}/getUpdateReportForCatalog/{intID}",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def get_list(cls) -> List["Catalog"]:
|
|
73
|
+
"""
|
|
74
|
+
Use the get_list method instead.
|
|
75
|
+
|
|
76
|
+
Get all catalogs from database
|
|
77
|
+
|
|
78
|
+
:return: list of catalogs
|
|
79
|
+
:rtype: List["Catalog"]
|
|
80
|
+
"""
|
|
81
|
+
return cls._handle_list_response(cls._get_api_handler().get(cls.get_endpoint("get_list")))
|
|
82
|
+
|
|
83
|
+
def insert_catalog(self, app: Application) -> "Catalog": # noqa
|
|
84
|
+
"""
|
|
85
|
+
DEPRECATED: This method is deprecated and will be removed in a future version.
|
|
86
|
+
Use the create method instead.
|
|
87
|
+
|
|
88
|
+
Insert catalog into database
|
|
89
|
+
|
|
90
|
+
:param Application app: Application
|
|
91
|
+
:return: Newly created catalog object
|
|
92
|
+
:rtype: Catalog
|
|
93
|
+
"""
|
|
94
|
+
warnings.warn(
|
|
95
|
+
"insert_catalog is deprecated and will be removed in a future version. Use create method instead.",
|
|
96
|
+
DeprecationWarning,
|
|
97
|
+
)
|
|
98
|
+
# Convert the model to a dictionary
|
|
99
|
+
return self.create()
|
|
100
|
+
|
|
101
|
+
@staticmethod
|
|
102
|
+
def get_catalogs(app: Application) -> list:
|
|
103
|
+
"""
|
|
104
|
+
DEPRECATED: This method is deprecated and will be removed in a future version.
|
|
105
|
+
Use the get_list method instead.
|
|
106
|
+
|
|
107
|
+
Get all catalogs from database
|
|
108
|
+
|
|
109
|
+
:param Application app: Application
|
|
110
|
+
:raises APIRetrieveError: API request failed
|
|
111
|
+
:return: list of catalogs
|
|
112
|
+
:rtype: list
|
|
113
|
+
"""
|
|
114
|
+
warnings.warn(
|
|
115
|
+
"get_catalogs is deprecated and will be removed in a future version. Use get_list method instead.",
|
|
116
|
+
DeprecationWarning,
|
|
117
|
+
)
|
|
118
|
+
api = Api()
|
|
119
|
+
api_url = urljoin(app.config["domain"], "/api/catalogues")
|
|
120
|
+
response = api.get(api_url)
|
|
121
|
+
if not response.ok:
|
|
122
|
+
api.logger.debug(
|
|
123
|
+
f"API request failed with status: {response.status_code}: {response.reason} {response.text}"
|
|
124
|
+
)
|
|
125
|
+
raise APIRetrieveError(f"API request failed with status {response.status_code}")
|
|
126
|
+
return response.json()
|
|
127
|
+
|
|
128
|
+
@classmethod
|
|
129
|
+
def get_with_all_details(cls, catalog_id: int) -> Optional[dict]:
|
|
130
|
+
"""
|
|
131
|
+
Retrieves a catalog with all details by its ID.
|
|
132
|
+
|
|
133
|
+
:param int catalog_id: The ID of the catalog
|
|
134
|
+
:return: The response from the API or None
|
|
135
|
+
:rtype: Optional[dict]
|
|
136
|
+
"""
|
|
137
|
+
endpoint = cls.get_endpoint("get_catalog_with_all_details").format(
|
|
138
|
+
model_slug=cls.get_module_slug(), intID=catalog_id
|
|
139
|
+
)
|
|
140
|
+
response = cls._get_api_handler().get(endpoint)
|
|
141
|
+
|
|
142
|
+
if response and response.ok and response.status_code not in [204, 404]:
|
|
143
|
+
return response.json()
|
|
144
|
+
return {}
|
|
145
|
+
|
|
146
|
+
@classmethod
|
|
147
|
+
def get_update_report_for_catalog(
|
|
148
|
+
cls,
|
|
149
|
+
catalog_id: int,
|
|
150
|
+
) -> Response:
|
|
151
|
+
""" """
|
|
152
|
+
endpoint = cls.get_endpoint("get_update_report_for_catalog").format(
|
|
153
|
+
model_slug=cls.get_module_slug(),
|
|
154
|
+
intID=catalog_id,
|
|
155
|
+
)
|
|
156
|
+
response = cls._get_api_handler().get(endpoint)
|
|
157
|
+
|
|
158
|
+
return response
|
|
159
|
+
|
|
160
|
+
@classmethod
|
|
161
|
+
def get_updatable_catalogs(cls) -> Optional[list]:
|
|
162
|
+
"""
|
|
163
|
+
Get updatable catalogues
|
|
164
|
+
|
|
165
|
+
:return: List of updatable catalogues
|
|
166
|
+
:rtype: Optional[list]
|
|
167
|
+
"""
|
|
168
|
+
|
|
169
|
+
endpoint = cls.get_endpoint("get_updatable").format(model_slug=cls.get_module_slug())
|
|
170
|
+
response = cls._get_api_handler().get(endpoint)
|
|
171
|
+
if (
|
|
172
|
+
response
|
|
173
|
+
and response.ok
|
|
174
|
+
and response.status_code
|
|
175
|
+
not in [
|
|
176
|
+
204,
|
|
177
|
+
404,
|
|
178
|
+
]
|
|
179
|
+
):
|
|
180
|
+
return response.json()
|
|
181
|
+
return None
|
|
182
|
+
|
|
183
|
+
@classmethod
|
|
184
|
+
def update_regscale_catalog(
|
|
185
|
+
cls,
|
|
186
|
+
catalog_id: int,
|
|
187
|
+
) -> Union[Response | list]:
|
|
188
|
+
"""
|
|
189
|
+
Update a regscale catalog
|
|
190
|
+
|
|
191
|
+
:param int catalog_id: The ID of the catalog
|
|
192
|
+
:return: A Response object
|
|
193
|
+
:rtype: Union[Response | list]
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
endpoint = cls.get_endpoint("update_regscale_catalog").format(
|
|
197
|
+
model_slug=cls.get_module_slug(),
|
|
198
|
+
intID=catalog_id,
|
|
199
|
+
)
|
|
200
|
+
response = cls._get_api_handler().put(endpoint=endpoint) # data is optional here, not needed for this.
|
|
201
|
+
if (
|
|
202
|
+
response
|
|
203
|
+
and response.ok
|
|
204
|
+
and response.status_code
|
|
205
|
+
not in [
|
|
206
|
+
204,
|
|
207
|
+
404,
|
|
208
|
+
]
|
|
209
|
+
):
|
|
210
|
+
return response.json()
|
|
211
|
+
return response
|
|
212
|
+
|
|
213
|
+
@classmethod
|
|
214
|
+
def compare_and_update(
|
|
215
|
+
cls,
|
|
216
|
+
new_catalog: dict,
|
|
217
|
+
catalog_id: int,
|
|
218
|
+
format: str = "json",
|
|
219
|
+
structure: str = "flatReport",
|
|
220
|
+
apply_updates: bool = False,
|
|
221
|
+
) -> Response:
|
|
222
|
+
"""
|
|
223
|
+
Get updatable catalogues
|
|
224
|
+
|
|
225
|
+
:param dict new_catalog: The new catalog to compare
|
|
226
|
+
:param int catalog_id: The ID of the catalog
|
|
227
|
+
:param str format: The format of the catalog
|
|
228
|
+
:param str structure: The structure of the catalog
|
|
229
|
+
:param bool apply_updates: Whether to apply updates
|
|
230
|
+
:return: List of updatable catalogues
|
|
231
|
+
:rtype: Response
|
|
232
|
+
"""
|
|
233
|
+
bytes_object = json.dumps(new_catalog).encode("utf-8")
|
|
234
|
+
files = {"newCatalogFile": io.BytesIO(bytes_object)}
|
|
235
|
+
# convert files to bytes like object
|
|
236
|
+
endpoint = cls.get_endpoint("compare_and_update").format(
|
|
237
|
+
model_slug=cls.get_module_slug(),
|
|
238
|
+
intID=catalog_id,
|
|
239
|
+
format=format,
|
|
240
|
+
structure=structure,
|
|
241
|
+
apply_updates=apply_updates,
|
|
242
|
+
)
|
|
243
|
+
params = {
|
|
244
|
+
"format": format.lower(),
|
|
245
|
+
"structure": structure,
|
|
246
|
+
"applyUpdates": apply_updates,
|
|
247
|
+
}
|
|
248
|
+
response = cls._get_api_handler().post(endpoint=endpoint, files=files, params=params)
|
|
249
|
+
|
|
250
|
+
if (
|
|
251
|
+
response
|
|
252
|
+
and response.ok
|
|
253
|
+
and response.status_code
|
|
254
|
+
not in [
|
|
255
|
+
204,
|
|
256
|
+
404,
|
|
257
|
+
]
|
|
258
|
+
):
|
|
259
|
+
return response
|
|
260
|
+
cls.log_response_error(response, suppress_error=True)
|
|
261
|
+
return response
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Model for Control Parameter in the application"""
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from pydantic import ConfigDict
|
|
7
|
+
|
|
8
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CCI(RegScaleModel):
|
|
12
|
+
"""
|
|
13
|
+
CCI class
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
_module_slug = "cci"
|
|
17
|
+
_unique_fields = [
|
|
18
|
+
["parameterId", "securityControlId"],
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
id: Optional[int] = 0
|
|
22
|
+
uuid: Optional[str] = None
|
|
23
|
+
name: Optional[str] = None
|
|
24
|
+
description: Optional[str] = None
|
|
25
|
+
controlType: Optional[str] = None
|
|
26
|
+
publishDate: Optional[str] = None
|
|
27
|
+
securityControlId: Optional[int] = None
|
|
28
|
+
archived: bool = False
|
|
29
|
+
createdById: Optional[str] = None
|
|
30
|
+
dateCreated: Optional[str] = None
|
|
31
|
+
lastUpdatedById: Optional[str] = None
|
|
32
|
+
dateLastUpdated: Optional[str] = None
|
|
33
|
+
tenantsId: Optional[int] = None
|
|
34
|
+
isPublic: bool = True
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
38
|
+
"""
|
|
39
|
+
Get additional endpoints for the ControlParameter
|
|
40
|
+
|
|
41
|
+
:return: Additional endpoints for the ControlParameter
|
|
42
|
+
:rtype: ConfigDict
|
|
43
|
+
"""
|
|
44
|
+
return ConfigDict( # type: ignore
|
|
45
|
+
get_all_by_parent="/api/{model_slug}/getByControl/{intParentID}",
|
|
46
|
+
)
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module contains the Change model for RegScale.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from typing import Optional, List, Dict
|
|
8
|
+
|
|
9
|
+
from pydantic import ConfigDict, Field
|
|
10
|
+
|
|
11
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
12
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ChangeType(str, Enum):
|
|
18
|
+
"""
|
|
19
|
+
Enum for the ChangeType field in the Change model.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
emergency = "Emergency"
|
|
23
|
+
normal = "Normal"
|
|
24
|
+
standard = "Standard"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ChangePriority(str, Enum):
|
|
28
|
+
"""
|
|
29
|
+
Enum for the ChangePriority field in the Change model.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
critical = "Critical"
|
|
33
|
+
low = "Low"
|
|
34
|
+
moderate = "Moderate"
|
|
35
|
+
high = "High"
|
|
36
|
+
security = "Security"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ChangeStatus(str, Enum):
|
|
40
|
+
"""
|
|
41
|
+
Enum for the ChangeStatus field in the Change model.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
draft = "Draft"
|
|
45
|
+
assess = "Assess"
|
|
46
|
+
pending_approval = "Pending Approval"
|
|
47
|
+
approved = "Approved"
|
|
48
|
+
schedule = "Schedule"
|
|
49
|
+
implement = "Implement"
|
|
50
|
+
review = "Review"
|
|
51
|
+
complete = "Complete"
|
|
52
|
+
cancelled = "Cancelled"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ChangeOutageRequired(str, Enum):
|
|
56
|
+
"""
|
|
57
|
+
Enum for the ChangeOutageRequired field in the Change model.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
yes = "Yes"
|
|
61
|
+
no = "No"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class Change(RegScaleModel):
|
|
65
|
+
"""
|
|
66
|
+
A class to represent the Change model in RegScale.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
_module_id = 31
|
|
70
|
+
_module_slug = "changes"
|
|
71
|
+
_parent_id_field = "parentId"
|
|
72
|
+
|
|
73
|
+
id: Optional[int] = 0
|
|
74
|
+
isPublic: bool = True
|
|
75
|
+
uuid: Optional[str] = None
|
|
76
|
+
title: str
|
|
77
|
+
changeReason: str
|
|
78
|
+
description: Optional[str] = None
|
|
79
|
+
changeOwnerId: str = Field(default_factory=RegScaleModel.get_user_id)
|
|
80
|
+
dateRequested: str = Field(default_factory=get_current_datetime)
|
|
81
|
+
startChangeWindow: Optional[str] = None
|
|
82
|
+
endChangeWindow: Optional[str] = None
|
|
83
|
+
outageRequired: str = ChangeOutageRequired.no.value
|
|
84
|
+
outageSummary: Optional[str] = None
|
|
85
|
+
status: str = ChangeStatus.draft.value
|
|
86
|
+
dateChangeApproved: Optional[str] = None
|
|
87
|
+
dateWorkCompleted: Optional[str] = None
|
|
88
|
+
changeType: str = ChangeType.standard.value
|
|
89
|
+
priority: str = ChangePriority.moderate.value
|
|
90
|
+
securityImpactAssessment: Optional[str] = None
|
|
91
|
+
changePlan: Optional[str] = None
|
|
92
|
+
riskAssessment: Optional[str] = None
|
|
93
|
+
rollbackPlan: Optional[str] = None
|
|
94
|
+
communicationsPlan: Optional[str] = None
|
|
95
|
+
notes: Optional[str] = None
|
|
96
|
+
leadTesterId: Optional[str] = None
|
|
97
|
+
testPlan: Optional[str] = None
|
|
98
|
+
testResults: Optional[str] = None
|
|
99
|
+
dateTested: Optional[str] = None
|
|
100
|
+
facilityId: Optional[int] = None
|
|
101
|
+
orgId: Optional[int] = None
|
|
102
|
+
parentId: Optional[int] = None
|
|
103
|
+
parentModule: Optional[str] = None
|
|
104
|
+
dateLastUpdated: str = Field(default_factory=get_current_datetime)
|
|
105
|
+
|
|
106
|
+
# now create the _get_additional_endpoints method from this list of endpoints
|
|
107
|
+
@staticmethod
|
|
108
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
109
|
+
"""
|
|
110
|
+
Get additional endpoints for the Changes model.
|
|
111
|
+
|
|
112
|
+
:return: A dictionary of additional endpoints
|
|
113
|
+
:rtype: ConfigDict
|
|
114
|
+
"""
|
|
115
|
+
return ConfigDict(
|
|
116
|
+
get_count="/api/{model_slug}/getCount",
|
|
117
|
+
schedule="/api/{model_slug}/schedule/{year}/{strDateField}",
|
|
118
|
+
report="/api/{model_slug}/report/{strReport}",
|
|
119
|
+
filter_changes="/api/{model_slug}/filterChanges",
|
|
120
|
+
query_by_custom_field="/api/{model_slug}/queryByCustomField/{strFieldName}/{strValue}",
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
@classmethod
|
|
124
|
+
def filter_change(cls, payload: Dict) -> List["Change"]:
|
|
125
|
+
"""
|
|
126
|
+
Filter change based on query parameters.
|
|
127
|
+
|
|
128
|
+
:param dict payload: Query parameters
|
|
129
|
+
:return: A list of changes
|
|
130
|
+
"""
|
|
131
|
+
response = cls._get_api_handler().post(
|
|
132
|
+
endpoint=cls.get_endpoint("filter_changes").format(model_slug=cls._module_slug), data=payload
|
|
133
|
+
)
|
|
134
|
+
if response and response.ok:
|
|
135
|
+
return [cls(**ci) for ci in response.json().get("items", [])]
|
|
136
|
+
return []
|
|
137
|
+
|
|
138
|
+
@staticmethod
|
|
139
|
+
def fetch_all_changes() -> List["Change"]:
|
|
140
|
+
"""
|
|
141
|
+
Fetch all changes in RegScale
|
|
142
|
+
|
|
143
|
+
:return: List of Changes from RegScale
|
|
144
|
+
:rtype: List[Change]
|
|
145
|
+
"""
|
|
146
|
+
from regscale.core.app.api import Api
|
|
147
|
+
from requests import JSONDecodeError
|
|
148
|
+
|
|
149
|
+
api = Api()
|
|
150
|
+
body = f"""
|
|
151
|
+
query {{
|
|
152
|
+
changes(take: 50, skip: 0) {{
|
|
153
|
+
items {{
|
|
154
|
+
{Change.build_graphql_fields()}
|
|
155
|
+
}}
|
|
156
|
+
pageInfo {{
|
|
157
|
+
hasNextPage
|
|
158
|
+
}}
|
|
159
|
+
,totalCount}}
|
|
160
|
+
}}"""
|
|
161
|
+
try:
|
|
162
|
+
api.logger.info("Retrieving all changes from RegScale...")
|
|
163
|
+
existing_changes = api.graph(query=body)["changes"]["items"]
|
|
164
|
+
api.logger.info("Retrieved %i change(s) from RegScale.", len(existing_changes))
|
|
165
|
+
except (JSONDecodeError, KeyError):
|
|
166
|
+
existing_changes = []
|
|
167
|
+
return [Change(**change) for change in existing_changes]
|