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,125 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Model for Leveraged Authorizations in the application"""
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import Optional, Union
|
|
6
|
+
from urllib.parse import urljoin
|
|
7
|
+
|
|
8
|
+
from pydantic import field_validator, Field, ConfigDict
|
|
9
|
+
|
|
10
|
+
from regscale.core.app.api import Api
|
|
11
|
+
from regscale.core.app.application import Application
|
|
12
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
13
|
+
from .regscale_model import RegScaleModel
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class NatureOfAgreement(str, Enum):
|
|
17
|
+
"""Asset Status Enum"""
|
|
18
|
+
|
|
19
|
+
EULA = "End User Licensing Agreement (EULA)"
|
|
20
|
+
SLA = "Service Level Agreement (SLA)"
|
|
21
|
+
LicenseAgreement = "License Agreement"
|
|
22
|
+
Contract = "Contract"
|
|
23
|
+
Other = "Other"
|
|
24
|
+
|
|
25
|
+
def __str__(self):
|
|
26
|
+
return self.value
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ImpactLevel(str, Enum):
|
|
30
|
+
"""Asset Status Enum"""
|
|
31
|
+
|
|
32
|
+
LowSaaS = "Low Impact SaaS"
|
|
33
|
+
Low = "Low"
|
|
34
|
+
Moderate = "Moderate"
|
|
35
|
+
High = "High"
|
|
36
|
+
NonAuthorized = "Non-Authorized Cloud Service Provider (CSP)"
|
|
37
|
+
|
|
38
|
+
def __str__(self):
|
|
39
|
+
return self.value
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class LeveragedAuthorization(RegScaleModel):
|
|
43
|
+
"""LeveragedAuthorizations model."""
|
|
44
|
+
|
|
45
|
+
_module_slug = "leveraged-authorization"
|
|
46
|
+
_get_objects_for_list = True
|
|
47
|
+
|
|
48
|
+
id: Optional[int] = 0
|
|
49
|
+
isPublic: Optional[bool] = True
|
|
50
|
+
uuid: Optional[str] = None
|
|
51
|
+
title: str
|
|
52
|
+
fedrampId: Optional[str] = None
|
|
53
|
+
ownerId: str
|
|
54
|
+
securityPlanId: int
|
|
55
|
+
natureOfAgreement: Union[NatureOfAgreement, str] = NatureOfAgreement.Other
|
|
56
|
+
impactLevel: Union[ImpactLevel, str] = ImpactLevel.Low
|
|
57
|
+
dateAuthorized: Optional[str] = None
|
|
58
|
+
description: Optional[str] = None
|
|
59
|
+
dataTypes: Optional[str] = None
|
|
60
|
+
servicesUsed: Optional[str] = None
|
|
61
|
+
authenticationType: Optional[str] = None
|
|
62
|
+
authorizedUserTypes: Optional[str] = None
|
|
63
|
+
authorizationType: Optional[str] = None # not to be confused with authenticationType
|
|
64
|
+
securityPlanLink: Optional[str] = ""
|
|
65
|
+
crmLink: Optional[str] = ""
|
|
66
|
+
responsibilityAndInheritanceLink: Optional[str] = ""
|
|
67
|
+
createdById: str = Field(default_factory=RegScaleModel.get_user_id)
|
|
68
|
+
dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
69
|
+
lastUpdatedById: str = Field(default_factory=RegScaleModel.get_user_id)
|
|
70
|
+
dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
71
|
+
tenantsId: Optional[int] = 1
|
|
72
|
+
|
|
73
|
+
@staticmethod
|
|
74
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
75
|
+
"""
|
|
76
|
+
Get additional endpoints for the PortsProtocols model.
|
|
77
|
+
|
|
78
|
+
:return: A dictionary of additional endpoints
|
|
79
|
+
:rtype: ConfigDict
|
|
80
|
+
"""
|
|
81
|
+
return ConfigDict( # type: ignore
|
|
82
|
+
get_all_by_parent="/api/{model_slug}/getAllByParent/{intParentID}",
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
@field_validator(
|
|
87
|
+
"crmLink",
|
|
88
|
+
"responsibilityAndInheritanceLink",
|
|
89
|
+
"securityPlanLink",
|
|
90
|
+
mode="before",
|
|
91
|
+
check_fields=True,
|
|
92
|
+
)
|
|
93
|
+
def validate_fields(cls, value: Optional[str]) -> str:
|
|
94
|
+
"""
|
|
95
|
+
Validate the CRM link, responsibility and inheritance link, and security plan link.
|
|
96
|
+
|
|
97
|
+
:param Optional[str] value: The field value.
|
|
98
|
+
:return: The validated field value or empty string.
|
|
99
|
+
:rtype: str
|
|
100
|
+
"""
|
|
101
|
+
if not value:
|
|
102
|
+
value = ""
|
|
103
|
+
return value
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
def insert_leveraged_authorizations(app: Application, leveraged_auth: "LeveragedAuthorization") -> dict:
|
|
107
|
+
"""
|
|
108
|
+
Insert a leveraged authorization into the database.
|
|
109
|
+
|
|
110
|
+
:param Application app: The application instance.
|
|
111
|
+
:param LeveragedAuthorization leveraged_auth: The leveraged authorization to insert.
|
|
112
|
+
:return: The response from the API or raise an exception
|
|
113
|
+
:rtype: dict
|
|
114
|
+
"""
|
|
115
|
+
api = Api()
|
|
116
|
+
|
|
117
|
+
# Construct the URL by joining the domain and endpoint
|
|
118
|
+
url = urljoin(app.config.get("domain"), "/api/leveraged-authorization")
|
|
119
|
+
# Convert the Pydantic model to a dictionary
|
|
120
|
+
data = leveraged_auth.dict()
|
|
121
|
+
# Make the POST request to insert the data
|
|
122
|
+
response = api.post(url, json=data)
|
|
123
|
+
|
|
124
|
+
# Check for success and handle the response as needed
|
|
125
|
+
return response.json() if response.ok else response.raise_for_status()
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Optional, Union
|
|
3
|
+
|
|
4
|
+
from pydantic import Field, ConfigDict
|
|
5
|
+
|
|
6
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
7
|
+
from regscale.models.regscale_models import RegScaleModel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class LoIType(str, Enum):
|
|
11
|
+
"""Lines of Inquiry Type Enum"""
|
|
12
|
+
|
|
13
|
+
Audit = "Audit Question"
|
|
14
|
+
Data = "Data Collection"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class LinesOfInquiry(RegScaleModel):
|
|
18
|
+
"""Lines of Inquiry Model"""
|
|
19
|
+
|
|
20
|
+
_module_slug = "lines-of-inquiry"
|
|
21
|
+
_unique_fields = ["id"]
|
|
22
|
+
_parent_id_field = "assessmentPlanId"
|
|
23
|
+
|
|
24
|
+
id: int = 0
|
|
25
|
+
isPublic: bool = True
|
|
26
|
+
uuid: Optional[str] = None
|
|
27
|
+
inquiry: Optional[str] = None
|
|
28
|
+
requirement: Optional[str] = None
|
|
29
|
+
assessmentPlanId: int = 0
|
|
30
|
+
weight: Optional[int] = 1
|
|
31
|
+
lineType: Union[LoIType, str] = LoIType.Audit
|
|
32
|
+
dataType: Optional[str] = Field(default_factory=get_current_datetime)
|
|
33
|
+
choiceList: Optional[str] = None
|
|
34
|
+
requiresScoring: bool = True
|
|
35
|
+
createdBy: Optional[str] = None
|
|
36
|
+
createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
37
|
+
dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
38
|
+
lastUpdatedBy: Optional[str] = None
|
|
39
|
+
lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
40
|
+
dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
41
|
+
|
|
42
|
+
@staticmethod
|
|
43
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
44
|
+
"""
|
|
45
|
+
Get additional endpoints for the Components model.
|
|
46
|
+
|
|
47
|
+
:return: A dictionary of additional endpoints
|
|
48
|
+
:rtype: ConfigDict
|
|
49
|
+
"""
|
|
50
|
+
return ConfigDict( # type: ignore
|
|
51
|
+
get_all_by_parent="/api/{model_slug}/getAllByParent/{intAssessmentID}",
|
|
52
|
+
)
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"""Model for a RegScale Link"""
|
|
2
|
+
|
|
3
|
+
import warnings
|
|
4
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
5
|
+
from typing import List, Optional
|
|
6
|
+
|
|
7
|
+
from pydantic import ConfigDict, Field
|
|
8
|
+
from requests import JSONDecodeError, Response
|
|
9
|
+
|
|
10
|
+
from regscale.core.app.api import Api
|
|
11
|
+
from regscale.core.app.application import Application
|
|
12
|
+
from regscale.core.app.logz import create_logger
|
|
13
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
14
|
+
from .regscale_model import RegScaleModel
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Link(RegScaleModel):
|
|
18
|
+
_module_slug = "links"
|
|
19
|
+
_unique_fields = [
|
|
20
|
+
["title", "parentID", "parentModule"],
|
|
21
|
+
]
|
|
22
|
+
_parent_id_field = "parentID"
|
|
23
|
+
|
|
24
|
+
id: Optional[int] = 0
|
|
25
|
+
url: str
|
|
26
|
+
title: str
|
|
27
|
+
createdById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
28
|
+
dateCreated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
29
|
+
lastUpdatedById: Optional[str] = Field(default_factory=RegScaleModel.get_user_id)
|
|
30
|
+
isPublic: bool = True
|
|
31
|
+
parentID: Optional[int] = None
|
|
32
|
+
parentModule: Optional[str] = None
|
|
33
|
+
tenantsId: Optional[int] = None
|
|
34
|
+
dateLastUpdated: Optional[str] = Field(default_factory=get_current_datetime)
|
|
35
|
+
otherAttributes: Optional[str] = None
|
|
36
|
+
externalId: Optional[str] = None
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
40
|
+
"""
|
|
41
|
+
Get additional endpoints for the Links model.
|
|
42
|
+
|
|
43
|
+
:return: A dictionary of additional endpoints
|
|
44
|
+
:rtype: ConfigDict
|
|
45
|
+
"""
|
|
46
|
+
return ConfigDict(
|
|
47
|
+
get_all_by_part="/api/{model_slug}/getAllByPart/{intParentID}/{strModule}/{strType}/{strPart}",
|
|
48
|
+
get_all_from_list="/api/{model_slug}/getAllFromList",
|
|
49
|
+
batch_create="/api/{model_slug}/batchCreate",
|
|
50
|
+
batch_update="/api/{model_slug}/batchUpdate",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def __hash__(self) -> hash:
|
|
54
|
+
"""
|
|
55
|
+
Enable object to be hashable
|
|
56
|
+
|
|
57
|
+
:return: Hashed Link
|
|
58
|
+
:rtype: hash
|
|
59
|
+
"""
|
|
60
|
+
return hash(
|
|
61
|
+
(
|
|
62
|
+
self.title,
|
|
63
|
+
self.parentID,
|
|
64
|
+
self.parentModule,
|
|
65
|
+
self.url,
|
|
66
|
+
)
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def __eq__(self, other: "Link") -> bool:
|
|
70
|
+
"""
|
|
71
|
+
Determine if two Links are equal
|
|
72
|
+
|
|
73
|
+
:param Link other: Link Object to compare to
|
|
74
|
+
:return: True if equal
|
|
75
|
+
:rtype: bool
|
|
76
|
+
"""
|
|
77
|
+
return (
|
|
78
|
+
self.title == other.title
|
|
79
|
+
and self.parentID == other.parentID
|
|
80
|
+
and self.parentModule == other.parentModule
|
|
81
|
+
and self.url == other.url
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
@staticmethod
|
|
85
|
+
def update_link(app: Application, link: "Link") -> Optional["Link"]:
|
|
86
|
+
"""
|
|
87
|
+
Update a Link in RegScale via API
|
|
88
|
+
|
|
89
|
+
:param Application app: Application
|
|
90
|
+
:param Link link: Link to update
|
|
91
|
+
:return: Updated Link
|
|
92
|
+
:rtype: Optional[Link]
|
|
93
|
+
"""
|
|
94
|
+
warnings.warn(
|
|
95
|
+
"This function is deprecated and will be removed in the future. Use Link.save() instead.",
|
|
96
|
+
DeprecationWarning,
|
|
97
|
+
stacklevel=2,
|
|
98
|
+
)
|
|
99
|
+
api = Api()
|
|
100
|
+
link_id = link.id
|
|
101
|
+
|
|
102
|
+
response = api.put(app.config["domain"] + f"/api/links/{link_id}", json=link.dict())
|
|
103
|
+
if response.status_code == 200:
|
|
104
|
+
try:
|
|
105
|
+
link = Link(**response.json())
|
|
106
|
+
except JSONDecodeError:
|
|
107
|
+
link = None
|
|
108
|
+
return link
|
|
109
|
+
|
|
110
|
+
@staticmethod
|
|
111
|
+
def bulk_insert(api: Api, links: List["Link"], thread_count: Optional[int] = 10) -> List[Response]:
|
|
112
|
+
"""
|
|
113
|
+
Bulk insert Links to the RegScale API
|
|
114
|
+
|
|
115
|
+
:param Api api: RegScale API
|
|
116
|
+
:param List[Link] links: List of links to insert
|
|
117
|
+
:param Optional[int] thread_count: Number of threads to use, defaults to 10
|
|
118
|
+
:return: List of Responses from RegScale API
|
|
119
|
+
:rtype: List[Response]
|
|
120
|
+
"""
|
|
121
|
+
warnings.warn(
|
|
122
|
+
"This function is deprecated and will be removed in the future. Use Link.batch_create() instead.",
|
|
123
|
+
DeprecationWarning,
|
|
124
|
+
stacklevel=2,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
app = api.app
|
|
128
|
+
results = []
|
|
129
|
+
|
|
130
|
+
# use threadpoolexecutor to speed up inserts
|
|
131
|
+
with ThreadPoolExecutor(max_workers=thread_count) as executor:
|
|
132
|
+
futures = [
|
|
133
|
+
executor.submit(
|
|
134
|
+
Link.insert_link,
|
|
135
|
+
app,
|
|
136
|
+
link,
|
|
137
|
+
)
|
|
138
|
+
for link in links
|
|
139
|
+
]
|
|
140
|
+
for future in as_completed(futures):
|
|
141
|
+
results.append(future.result())
|
|
142
|
+
return results
|
|
143
|
+
|
|
144
|
+
@staticmethod
|
|
145
|
+
def insert_link(app: Application, link: "Link") -> "Link":
|
|
146
|
+
"""
|
|
147
|
+
Insert a Link into RegScale
|
|
148
|
+
|
|
149
|
+
:param Application app: Application
|
|
150
|
+
:param Link link: Link to insert
|
|
151
|
+
:return: Inserted Link
|
|
152
|
+
:rtype: Link
|
|
153
|
+
"""
|
|
154
|
+
warnings.warn(
|
|
155
|
+
"This function is deprecated and will be removed in the future. Use Link.create() instead.",
|
|
156
|
+
DeprecationWarning,
|
|
157
|
+
stacklevel=2,
|
|
158
|
+
)
|
|
159
|
+
api = Api()
|
|
160
|
+
logger = create_logger()
|
|
161
|
+
response = api.post(app.config["domain"] + "/api/links", json=link.dict())
|
|
162
|
+
if response.status_code == 200:
|
|
163
|
+
try:
|
|
164
|
+
link = Link(**response.json())
|
|
165
|
+
except JSONDecodeError as jex:
|
|
166
|
+
logger.error("Unable to read link:\n%s", jex)
|
|
167
|
+
link = None
|
|
168
|
+
else:
|
|
169
|
+
logger.warning("Unable to insert link: %s", link.title)
|
|
170
|
+
return link
|
|
171
|
+
|
|
172
|
+
@staticmethod
|
|
173
|
+
def fetch_links_by_parent(
|
|
174
|
+
app: Application,
|
|
175
|
+
regscale_id: int,
|
|
176
|
+
regscale_module: str,
|
|
177
|
+
) -> List["Link"]:
|
|
178
|
+
"""
|
|
179
|
+
Fetch Links by Parent ID and Module
|
|
180
|
+
|
|
181
|
+
:param Application app: Application
|
|
182
|
+
:param int regscale_id: RegScale ID
|
|
183
|
+
:param str regscale_module: RegScale Module
|
|
184
|
+
:return: List of Links
|
|
185
|
+
:rtype: List[Link]
|
|
186
|
+
"""
|
|
187
|
+
api = Api()
|
|
188
|
+
body = f"""
|
|
189
|
+
query {{
|
|
190
|
+
links(take: 50, skip: 0, where: {{ parentModule: {{eq: "{regscale_module}"}} parentID: {{eq: {regscale_id}}}
|
|
191
|
+
}}) {{
|
|
192
|
+
items {{
|
|
193
|
+
{Link.build_graphql_fields()}
|
|
194
|
+
}},
|
|
195
|
+
pageInfo {{
|
|
196
|
+
hasNextPage
|
|
197
|
+
}}
|
|
198
|
+
,totalCount}}
|
|
199
|
+
}}
|
|
200
|
+
"""
|
|
201
|
+
try:
|
|
202
|
+
existing_regscale_links = api.graph(query=body)["links"]["items"]
|
|
203
|
+
except (JSONDecodeError, KeyError):
|
|
204
|
+
existing_regscale_links = []
|
|
205
|
+
return [Link(**link) for link in existing_regscale_links]
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Metadata model for RegScale"""
|
|
2
|
+
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import Field, ConfigDict
|
|
6
|
+
|
|
7
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
8
|
+
from .regscale_model import RegScaleModel
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Metadata(RegScaleModel):
|
|
12
|
+
"""RegScale Metadata class"""
|
|
13
|
+
|
|
14
|
+
_module_slug = "metadata"
|
|
15
|
+
|
|
16
|
+
id: Optional[int] = None
|
|
17
|
+
isPublic: bool = True # Required as boolean
|
|
18
|
+
active: bool = True # Required as boolean
|
|
19
|
+
readOnly: bool = False # Required as boolean
|
|
20
|
+
field: Optional[str] = None
|
|
21
|
+
value: Optional[str] = None
|
|
22
|
+
type: Optional[str] = None
|
|
23
|
+
module: Optional[str] = None
|
|
24
|
+
tenantsId: int = 1
|
|
25
|
+
lastUpdatedById: Optional[str] = None
|
|
26
|
+
createdById: Optional[str] = None
|
|
27
|
+
dateCreated: str = Field(default_factory=get_current_datetime) # Required as string
|
|
28
|
+
dateLastUpdated: str = Field(default_factory=get_current_datetime) # Required as string
|
|
29
|
+
dateLastUpdated: str = Field(default_factory=get_current_datetime) # Required as string
|
|
30
|
+
mappedValue: Optional[str] = None
|
|
31
|
+
externalKey: Optional[str] = None
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
def _get_additional_endpoints() -> ConfigDict:
|
|
35
|
+
"""
|
|
36
|
+
Get additional endpoints for the Metadata model.
|
|
37
|
+
|
|
38
|
+
:return: A dictionary of additional endpoints
|
|
39
|
+
:rtype: ConfigDict
|
|
40
|
+
"""
|
|
41
|
+
return ConfigDict(
|
|
42
|
+
get_all_grouped="/api/{model_slug}/getAllGrouped",
|
|
43
|
+
filter_metadata="/api/{model_slug}/filterMetadata/{strModule}/{strField}/{strSortBy}/{strDirection}/{intPage}/{intPageSize}",
|
|
44
|
+
get_metadata_by_module_field="/api/{model_slug}/getMetadata/{strModule}/{strField}",
|
|
45
|
+
get_metadata_by_module="/api/{model_slug}/getMetadata/{strModule}",
|
|
46
|
+
get_seeding_options="/api/{model_slug}/getSeedingOptions",
|
|
47
|
+
reseed="/api/{model_slug}/reseed/{strModule}",
|
|
48
|
+
toggle_metadata="/api/{model_slug}/toggleMetadata/{intId}/{bToggle}",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def get_metadata_by_module_field(cls, module: str, field: str) -> List["Metadata"]:
|
|
53
|
+
"""
|
|
54
|
+
Retrieves metadata by module and field.
|
|
55
|
+
|
|
56
|
+
:param str module: The module
|
|
57
|
+
:param str field: The field
|
|
58
|
+
:return: A list of metadata or None
|
|
59
|
+
:rtype: List[Metadata]
|
|
60
|
+
"""
|
|
61
|
+
response = cls._get_api_handler().get(
|
|
62
|
+
endpoint=cls.get_endpoint("get_metadata_by_module_field").format(strModule=module, strField=field)
|
|
63
|
+
)
|
|
64
|
+
return cls._handle_list_response(response)
|
|
File without changes
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module contains the PlanCacheMixin class, which provides caching functionality for objects associated with security plans.
|
|
3
|
+
|
|
4
|
+
The PlanCacheMixin is a generic class that can be used with any model that has a security plan ID. It offers methods to populate a cache of objects by plan ID and retrieve all objects for a given plan ID.
|
|
5
|
+
|
|
6
|
+
Classes that inherit from PlanCacheMixin should define two class variables:
|
|
7
|
+
- _graph_query_name: A string representing the name of the GraphQL query for the objects.
|
|
8
|
+
- _graph_plan_id_path: A dot notation string representing the path to the security plan ID in the GraphQL response.
|
|
9
|
+
|
|
10
|
+
Example usage:
|
|
11
|
+
class AssetMapping(PlanCacheMixin["AssetMapping"]):
|
|
12
|
+
_graph_query_name = "assetMappings"
|
|
13
|
+
_graph_plan_id_path = "component.securityPlanId"
|
|
14
|
+
|
|
15
|
+
This mixin is designed to work with the RegScale API and assumes the existence of certain methods like cache_object.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import logging
|
|
19
|
+
from typing import Dict, List, TypeVar, Generic, cast, Type, ClassVar
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger("regscale")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
T = TypeVar("T", bound="PlanCacheMixin")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class PlanCacheMixin(Generic[T]):
|
|
28
|
+
"""
|
|
29
|
+
Mixin for caching objects by plan ID.
|
|
30
|
+
|
|
31
|
+
This mixin is designed to be used with classes that have a security plan ID.
|
|
32
|
+
It provides a method to populate a cache of objects by plan ID and a method to get all objects for a given plan ID.
|
|
33
|
+
|
|
34
|
+
Example:
|
|
35
|
+
class AssetMapping(PlanCacheMixin["AssetMapping"]):
|
|
36
|
+
_graph_query_name = "assetMappings"
|
|
37
|
+
_graph_plan_id_path = "component.securityPlanId"
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
_graph_query_name: ClassVar[str] # Example: "assetMappings"
|
|
41
|
+
_graph_plan_id_path: ClassVar[str] # Example: "component.securityPlanId"
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def populate_cache_by_plan(cls: Type[T], plan_id: int) -> None:
|
|
45
|
+
"""
|
|
46
|
+
Populate the parent cache using the get_plan_objects method.
|
|
47
|
+
|
|
48
|
+
:param int plan_id: Security Plan ID
|
|
49
|
+
:rtype: None
|
|
50
|
+
"""
|
|
51
|
+
objects = cls.get_plan_objects(plan_id)
|
|
52
|
+
for obj in objects:
|
|
53
|
+
cls.cache_object(obj)
|
|
54
|
+
logger.info("Cached %s %s objects", len(objects), cls.__name__)
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def get_plan_objects(cls: Type[T], plan_id: int) -> List[T]:
|
|
58
|
+
"""
|
|
59
|
+
Get all objects for a given plan ID.
|
|
60
|
+
|
|
61
|
+
:param int plan_id: Security Plan ID
|
|
62
|
+
:return: Objects for a given plan ID
|
|
63
|
+
:rtype: List[T]
|
|
64
|
+
"""
|
|
65
|
+
plan_id_field = cls._graph_plan_id_path
|
|
66
|
+
|
|
67
|
+
# Parse the dot notation to build the where statement
|
|
68
|
+
where_parts = plan_id_field.split(".")
|
|
69
|
+
where_statement = ": {".join(where_parts) + f": {{eq: {plan_id}}}" + "}" * (len(where_parts) - 1)
|
|
70
|
+
|
|
71
|
+
search_query = f"""query {{
|
|
72
|
+
{cls._graph_query_name}(skip: 0, take: 50, where: {{{where_statement}}}) {{
|
|
73
|
+
items {{
|
|
74
|
+
{cls.build_graphql_fields()}
|
|
75
|
+
}}
|
|
76
|
+
totalCount
|
|
77
|
+
pageInfo {{
|
|
78
|
+
hasNextPage
|
|
79
|
+
}}
|
|
80
|
+
}}
|
|
81
|
+
}}"""
|
|
82
|
+
response = cls._get_api_handler().graph(query=search_query)
|
|
83
|
+
objects = cast(List[T], cls._handle_graph_response(response))
|
|
84
|
+
return objects
|
|
85
|
+
|
|
86
|
+
@classmethod
|
|
87
|
+
def build_graphql_fields(cls) -> str:
|
|
88
|
+
"""
|
|
89
|
+
Build GraphQL fields for the query.
|
|
90
|
+
|
|
91
|
+
:return: GraphQL fields
|
|
92
|
+
:rtype: str
|
|
93
|
+
"""
|
|
94
|
+
raise NotImplementedError("Subclasses must implement build_graphql_fields")
|
|
95
|
+
|
|
96
|
+
@classmethod
|
|
97
|
+
def cache_object(cls, obj: T) -> None:
|
|
98
|
+
"""
|
|
99
|
+
Cache an object.
|
|
100
|
+
|
|
101
|
+
:param T obj: Object to cache
|
|
102
|
+
:rtype: None
|
|
103
|
+
"""
|
|
104
|
+
raise NotImplementedError("Subclasses must implement cache_object")
|
|
105
|
+
|
|
106
|
+
@classmethod
|
|
107
|
+
def _handle_graph_response(cls, response: Dict) -> List[T]:
|
|
108
|
+
"""
|
|
109
|
+
Handle GraphQL response.
|
|
110
|
+
|
|
111
|
+
:param Dict response: GraphQL response
|
|
112
|
+
:return: List of objects
|
|
113
|
+
:rtype: List[T]
|
|
114
|
+
"""
|
|
115
|
+
raise NotImplementedError("Subclasses must implement _handle_graph_response")
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def _api_handler(self):
|
|
119
|
+
"""
|
|
120
|
+
Get API handler.
|
|
121
|
+
|
|
122
|
+
:return: API handler
|
|
123
|
+
"""
|
|
124
|
+
raise NotImplementedError("Subclasses must implement _api_handler")
|