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,697 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
"""Script to parse a .xlsx file and load the inventory into RegScale as assets"""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from urllib.parse import urljoin
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
from openpyxl import load_workbook
|
|
10
|
+
from openpyxl.worksheet.worksheet import Worksheet
|
|
11
|
+
from rich.progress import track
|
|
12
|
+
|
|
13
|
+
from regscale.core.app.logz import create_logger
|
|
14
|
+
from regscale.models import (
|
|
15
|
+
SecurityPlan,
|
|
16
|
+
Catalog,
|
|
17
|
+
ControlImplementation,
|
|
18
|
+
ControlImplementationStatus,
|
|
19
|
+
CustomField,
|
|
20
|
+
CustomFieldsData,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
NOT_APPLICABLE = "Not Applicable"
|
|
24
|
+
logger = create_logger()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ControlImportMeta:
|
|
28
|
+
def __init__(self, control_id: str, import_row: int):
|
|
29
|
+
self.control_id = control_id
|
|
30
|
+
self.import_row = import_row
|
|
31
|
+
self.implementation_id = 0
|
|
32
|
+
self.parent_id = 0
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def import_emass_slcm_file(file_name: click.Path, regscale_id: int, catalogue_id: int, tenant_id: int) -> None:
|
|
36
|
+
"""
|
|
37
|
+
This function imports a SLCM export created by an eMASS system.
|
|
38
|
+
|
|
39
|
+
:param click.Path file_name:
|
|
40
|
+
:param int regscale_id:
|
|
41
|
+
:param int catalogue_id:
|
|
42
|
+
:param int tenant_id:
|
|
43
|
+
:return None:
|
|
44
|
+
:rtype None:
|
|
45
|
+
"""
|
|
46
|
+
if not verify_sp_id(regscale_id):
|
|
47
|
+
return logger.error("Not a valid Security Plan ID. Aborting!")
|
|
48
|
+
if not verify_cat_id(catalogue_id):
|
|
49
|
+
return logger.error("Not a valid Catalog ID. Aborting!")
|
|
50
|
+
if not os.path.isfile(file_name):
|
|
51
|
+
return logger.error("No file name/path provided to import. Aborting!")
|
|
52
|
+
custom_fields = check_for_custom_fields(tenant_id)
|
|
53
|
+
wb_obj = load_workbook(file_name)
|
|
54
|
+
ws = wb_obj.active
|
|
55
|
+
control_list = build_list_of_controls(ws)
|
|
56
|
+
control_list = get_or_initialize_control_implementation(control_list, regscale_id, catalogue_id)
|
|
57
|
+
identify_controls_to_remove(control_list, regscale_id)
|
|
58
|
+
for cur_control_index in track(
|
|
59
|
+
range(len(control_list)), description="Loading SLCM Control Implementations updates..."
|
|
60
|
+
):
|
|
61
|
+
cur_control = control_list[cur_control_index]
|
|
62
|
+
process_row(ws, cur_control, regscale_id, custom_fields)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def build_list_of_controls(ws: Worksheet) -> list:
|
|
66
|
+
"""
|
|
67
|
+
Builds a list of controls to import, so any missing can be created.
|
|
68
|
+
|
|
69
|
+
:param Worksheet ws:
|
|
70
|
+
:return list:
|
|
71
|
+
:rtype list:
|
|
72
|
+
"""
|
|
73
|
+
control_list = []
|
|
74
|
+
row = 7
|
|
75
|
+
control_id = ws.cell(row=row, column=1).value
|
|
76
|
+
while control_id is not None:
|
|
77
|
+
control_list.append(ControlImportMeta(control_id, row))
|
|
78
|
+
row += 1
|
|
79
|
+
control_id = ws.cell(row=row, column=1).value
|
|
80
|
+
return control_list
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def identify_controls_to_remove(control_list: list, regscale_id: int) -> None:
|
|
84
|
+
"""
|
|
85
|
+
Identifies controls that are in the security plan but not in the import, and designate them for deletion.
|
|
86
|
+
|
|
87
|
+
:param list control_list:
|
|
88
|
+
:param int regscale_id:
|
|
89
|
+
:return None:
|
|
90
|
+
:rtype None:
|
|
91
|
+
"""
|
|
92
|
+
current_implementations = get_all_current_control_implementation(regscale_id)
|
|
93
|
+
if current_implementations is not None:
|
|
94
|
+
for cur_control_index in track(
|
|
95
|
+
range(len(current_implementations)), description="Identifying SLCM Control Implementations to remove..."
|
|
96
|
+
):
|
|
97
|
+
cur_implementation = current_implementations[cur_control_index]
|
|
98
|
+
verify_control_implementation_to_remove(cur_implementation, control_list)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def verify_control_implementation_to_remove(control: dict, control_list: list) -> None:
|
|
102
|
+
"""
|
|
103
|
+
Verifies whether a control implementation is in the import, and if not, deletes it from the SP.
|
|
104
|
+
|
|
105
|
+
:param dict control:
|
|
106
|
+
:param list control_list:
|
|
107
|
+
:return None:
|
|
108
|
+
:rtype None:
|
|
109
|
+
"""
|
|
110
|
+
control_id = control["controlName"]
|
|
111
|
+
if find_control_in_metadata_list(control_list, control_id) is None:
|
|
112
|
+
remove_control_implementation(control)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def remove_control_implementation(control: dict) -> None:
|
|
116
|
+
"""
|
|
117
|
+
Deletes the control implementation from the security plan.
|
|
118
|
+
|
|
119
|
+
:param dict control:
|
|
120
|
+
:return None:
|
|
121
|
+
:rtype None:
|
|
122
|
+
"""
|
|
123
|
+
from regscale.core.app.api import Api
|
|
124
|
+
|
|
125
|
+
api = Api()
|
|
126
|
+
control_id = control["id"]
|
|
127
|
+
conmon_url = urljoin(api.config["domain"], f"/api/controlImplementation/{control_id}")
|
|
128
|
+
conmon_response = api.delete(conmon_url)
|
|
129
|
+
if not conmon_response.ok:
|
|
130
|
+
logger.warning("Unable to delete control implementation %s", control_id)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def get_or_initialize_control_implementation(control_list: list, regscale_id: int, catalogue_id: int) -> list:
|
|
134
|
+
"""
|
|
135
|
+
Retrieves all control implementations associated with the security plan.
|
|
136
|
+
|
|
137
|
+
:param list control_list:
|
|
138
|
+
:param int regscale_id:
|
|
139
|
+
:param int catalogue_id:
|
|
140
|
+
:return list:
|
|
141
|
+
:rtype list:
|
|
142
|
+
"""
|
|
143
|
+
current_implementations = get_all_current_control_implementation(regscale_id)
|
|
144
|
+
if current_implementations is not None:
|
|
145
|
+
control_list = match_control_rows(control_list, current_implementations)
|
|
146
|
+
return create_control_implementations(control_list, regscale_id, catalogue_id)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def get_all_current_control_implementation(regscale_id: int) -> Optional[list]:
|
|
150
|
+
"""
|
|
151
|
+
Retrieves the current set of control implementations associated with the security plan.
|
|
152
|
+
|
|
153
|
+
:param int regscale_id:
|
|
154
|
+
:return list:
|
|
155
|
+
:rtype list:
|
|
156
|
+
"""
|
|
157
|
+
from regscale.core.app.api import Api
|
|
158
|
+
|
|
159
|
+
api = Api()
|
|
160
|
+
# Using the REST API as the Security Control name is dropped by the model
|
|
161
|
+
conmon_url = urljoin(api.config["domain"], f"/api/controlImplementation/getAllByPlan/{regscale_id}")
|
|
162
|
+
conmon_response = api.get(conmon_url)
|
|
163
|
+
if conmon_response.ok:
|
|
164
|
+
try:
|
|
165
|
+
cil_json = conmon_response.json()
|
|
166
|
+
if len(cil_json) > 0:
|
|
167
|
+
return cil_json
|
|
168
|
+
except Exception:
|
|
169
|
+
return None
|
|
170
|
+
return None
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def create_control_implementations(control_list: list, regscale_id: int, catalogue_id: int) -> list:
|
|
174
|
+
"""
|
|
175
|
+
Retrieves all security controls associated with the catalog.
|
|
176
|
+
|
|
177
|
+
:param list control_list:
|
|
178
|
+
:param int regscale_id:
|
|
179
|
+
:param int catalogue_id:
|
|
180
|
+
:return list:
|
|
181
|
+
:rtype list:
|
|
182
|
+
"""
|
|
183
|
+
from regscale.core.app.api import Api
|
|
184
|
+
|
|
185
|
+
api = Api()
|
|
186
|
+
conmon_url = urljoin(api.config["domain"], f"/api/SecurityControls/getList/{catalogue_id}")
|
|
187
|
+
conmon_response = api.get(conmon_url)
|
|
188
|
+
if conmon_response.ok:
|
|
189
|
+
try:
|
|
190
|
+
scl_json = conmon_response.json()
|
|
191
|
+
if len(scl_json) > 0:
|
|
192
|
+
control_list = match_control_parent_rows(control_list, scl_json, regscale_id)
|
|
193
|
+
except Exception:
|
|
194
|
+
return control_list
|
|
195
|
+
return control_list
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def match_control_parent_rows(control_list: list, sec_control_list: list, regscale_id: int) -> list:
|
|
199
|
+
"""
|
|
200
|
+
Matches the control IDs from the SLCM import and the list of controls associated with the security plan.
|
|
201
|
+
|
|
202
|
+
:param list control_list:
|
|
203
|
+
:param list sec_control_list:
|
|
204
|
+
:param int regscale_id:
|
|
205
|
+
:param int catalogue_id:
|
|
206
|
+
:return list:
|
|
207
|
+
:rtype list:
|
|
208
|
+
"""
|
|
209
|
+
rtn_list = []
|
|
210
|
+
for cur_control_index in track(range(len(control_list)), description="Creating missing control implementations..."):
|
|
211
|
+
cur_meta = control_list[cur_control_index]
|
|
212
|
+
if cur_meta.implementation_id == 0:
|
|
213
|
+
sec_ctl = find_control_in_list(sec_control_list, cur_meta.control_id, "controlId")
|
|
214
|
+
if sec_ctl is not None:
|
|
215
|
+
cur_meta.parent_id = sec_ctl["id"]
|
|
216
|
+
cur_meta.implementation_id = create_control_implementation(sec_ctl, regscale_id)
|
|
217
|
+
rtn_list.append(cur_meta)
|
|
218
|
+
return rtn_list
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def create_control_implementation(sec_control: dict, regscale_id: int) -> int:
|
|
222
|
+
"""
|
|
223
|
+
Creates a control implementation that is in the import but currently doesn't exist in the security plan.
|
|
224
|
+
|
|
225
|
+
:param sec_control:
|
|
226
|
+
:param regscale_id:
|
|
227
|
+
:return:
|
|
228
|
+
"""
|
|
229
|
+
from regscale.core.app.api import Api
|
|
230
|
+
|
|
231
|
+
config = Api().config
|
|
232
|
+
updated_control_imp = sec_control
|
|
233
|
+
ctrl_imp = ControlImplementation.create_new_control_implementation(
|
|
234
|
+
sec_control, regscale_id, "securityplans", ControlImplementationStatus.NotImplemented, config["userId"]
|
|
235
|
+
)
|
|
236
|
+
try:
|
|
237
|
+
if isinstance(ctrl_imp, dict):
|
|
238
|
+
updated_control_imp = ctrl_imp
|
|
239
|
+
return save_new_control_implementation(updated_control_imp)
|
|
240
|
+
except Exception as ex:
|
|
241
|
+
logger.error(f"Unable to save new control implementation - {ex}")
|
|
242
|
+
return 0
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def save_new_control_implementation(control_imp: dict) -> int:
|
|
246
|
+
"""
|
|
247
|
+
Saves a new control implementation
|
|
248
|
+
|
|
249
|
+
:param dict control_imp:
|
|
250
|
+
:return int:
|
|
251
|
+
:rtype int:
|
|
252
|
+
"""
|
|
253
|
+
from regscale.core.app.api import Api
|
|
254
|
+
|
|
255
|
+
api = Api()
|
|
256
|
+
# Using the REST API as the model throws errors when some non-required data elements aren't populated
|
|
257
|
+
conmon_url = urljoin(api.config["domain"], "/api/controlImplementation/")
|
|
258
|
+
conmon_response = api.post(conmon_url, json=control_imp)
|
|
259
|
+
if conmon_response.ok:
|
|
260
|
+
scl_json = conmon_response.json()
|
|
261
|
+
return scl_json["id"]
|
|
262
|
+
else:
|
|
263
|
+
logger.error(conmon_response)
|
|
264
|
+
return 0
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def check_for_custom_fields(tenant_id: int) -> list:
|
|
268
|
+
"""
|
|
269
|
+
Retrieves the custom fields that some SLCM values are populated into.
|
|
270
|
+
|
|
271
|
+
:param int tenant_id:
|
|
272
|
+
:return list:
|
|
273
|
+
:rtype list:
|
|
274
|
+
"""
|
|
275
|
+
from regscale.core.app.api import Api
|
|
276
|
+
|
|
277
|
+
api = Api()
|
|
278
|
+
cfl = CustomField.get_list_by_module_id(15)
|
|
279
|
+
if len(cfl) == 0:
|
|
280
|
+
conmon_url = urljoin(api.config["domain"], f"/api/customFields/module/{tenant_id}/15")
|
|
281
|
+
conmon_response = api.get(conmon_url)
|
|
282
|
+
if conmon_response.ok:
|
|
283
|
+
cfl_json = conmon_response.json()
|
|
284
|
+
return cfl_json
|
|
285
|
+
else:
|
|
286
|
+
logger.error(conmon_response)
|
|
287
|
+
return []
|
|
288
|
+
cfl_list = []
|
|
289
|
+
for cur_cfl in cfl:
|
|
290
|
+
cur_json = cur_cfl.dict()
|
|
291
|
+
cfl_list.append(cur_json)
|
|
292
|
+
return cfl_list
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def match_control_rows(control_list: list, control_imp_list: list) -> list:
|
|
296
|
+
"""
|
|
297
|
+
Matches the controls in the import with those that exist in the SP.
|
|
298
|
+
|
|
299
|
+
:param list control_list:
|
|
300
|
+
:param list control_imp_list:
|
|
301
|
+
:return list:
|
|
302
|
+
:rtype list:
|
|
303
|
+
"""
|
|
304
|
+
rtn_list = []
|
|
305
|
+
for cur_meta in control_list:
|
|
306
|
+
ctl_imp = find_control_in_list(control_imp_list, cur_meta.control_id, "controlName")
|
|
307
|
+
if ctl_imp is not None:
|
|
308
|
+
cur_meta.implementation_id = ctl_imp["id"]
|
|
309
|
+
cur_meta.parent_id = ctl_imp["controlID"]
|
|
310
|
+
rtn_list.append(cur_meta)
|
|
311
|
+
return rtn_list
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def find_control_in_list(control_imp_list: list, control_id: str, data_field: str) -> Optional[dict]:
|
|
315
|
+
"""
|
|
316
|
+
Finds the control from the import in the list of existing controls
|
|
317
|
+
|
|
318
|
+
:param list control_imp_list:
|
|
319
|
+
:param str control_id:
|
|
320
|
+
:param str data_field:
|
|
321
|
+
:return dict:
|
|
322
|
+
:rtype dict:
|
|
323
|
+
"""
|
|
324
|
+
for cur_imp in control_imp_list:
|
|
325
|
+
if cur_imp[data_field].upper() == control_id.upper():
|
|
326
|
+
return cur_imp
|
|
327
|
+
return None
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def find_control_in_metadata_list(control_imp_list: list, control_id: str) -> Optional[dict]:
|
|
331
|
+
"""
|
|
332
|
+
Finds the control from the import in the list of existing controls
|
|
333
|
+
|
|
334
|
+
:param list control_imp_list:
|
|
335
|
+
:param str control_id:
|
|
336
|
+
:param str data_field:
|
|
337
|
+
:return dict:
|
|
338
|
+
:rtype dict:
|
|
339
|
+
"""
|
|
340
|
+
for cur_imp in control_imp_list:
|
|
341
|
+
if cur_imp.control_id.upper() == control_id.upper():
|
|
342
|
+
return cur_imp
|
|
343
|
+
return None
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def process_row(ws: Worksheet, control: ControlImportMeta, regscale_id: int, custom_fields: list) -> None:
|
|
347
|
+
"""
|
|
348
|
+
Processes the current row in the import.
|
|
349
|
+
|
|
350
|
+
:param Worksheet ws:
|
|
351
|
+
:param ControlImportMeta control:
|
|
352
|
+
:param int regscale_id:
|
|
353
|
+
:param list custom_fields:
|
|
354
|
+
:return None:
|
|
355
|
+
:rtype None:
|
|
356
|
+
"""
|
|
357
|
+
control_imp = get_control_implementation(control.implementation_id)
|
|
358
|
+
if control_imp is None:
|
|
359
|
+
return
|
|
360
|
+
# Column B (2) - Control Title - Security Control (Parent Control) Title (should be from Catalog)
|
|
361
|
+
# Column C (3) - Control Information - Security Control Description (should be from Catalog)
|
|
362
|
+
# Column D (4) - Compliance Status - Last Assessment Result
|
|
363
|
+
status = ws.cell(row=control.import_row, column=4).value
|
|
364
|
+
control_imp.lastAssessmentResult = "Fail"
|
|
365
|
+
if status == "Compliant":
|
|
366
|
+
control_imp.lastAssessmentResult = "Pass"
|
|
367
|
+
if status == NOT_APPLICABLE:
|
|
368
|
+
control_imp.status = NOT_APPLICABLE
|
|
369
|
+
save_control_implementation_update(control_imp)
|
|
370
|
+
process_implementation(ws, control, control_imp, custom_fields)
|
|
371
|
+
process_slcm(ws, control, control_imp, custom_fields)
|
|
372
|
+
process_risk_assessment(ws, control, regscale_id, control_imp)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def save_control_implementation_update(control_imp: ControlImplementation) -> None:
|
|
376
|
+
"""
|
|
377
|
+
Saves the current control implementation
|
|
378
|
+
|
|
379
|
+
:param ControlImplementation control_imp:
|
|
380
|
+
:return None:
|
|
381
|
+
:rtype None:
|
|
382
|
+
"""
|
|
383
|
+
from regscale.core.app.api import Api
|
|
384
|
+
|
|
385
|
+
api = Api()
|
|
386
|
+
try:
|
|
387
|
+
control_imp.save(False)
|
|
388
|
+
except Exception:
|
|
389
|
+
control_imp_payload = control_imp.dict()
|
|
390
|
+
conmon_url = urljoin(api.config["domain"], f"/api/controlImplementation/{control_imp.id}")
|
|
391
|
+
conmon_response = api.put(conmon_url, json=control_imp_payload)
|
|
392
|
+
if conmon_response.ok:
|
|
393
|
+
scl_json = conmon_response.json()
|
|
394
|
+
if scl_json is None:
|
|
395
|
+
logger.error("Could not update")
|
|
396
|
+
else:
|
|
397
|
+
logger.error(conmon_response)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
def get_control_implementation(control_id: int) -> ControlImplementation:
|
|
401
|
+
"""
|
|
402
|
+
Retrieves the current control implementation
|
|
403
|
+
|
|
404
|
+
:param int control_id:
|
|
405
|
+
:return ControlImplementation:
|
|
406
|
+
:rtype ControlImplementation:
|
|
407
|
+
"""
|
|
408
|
+
# Using the model throws errors about missing data elements
|
|
409
|
+
from regscale.core.app.api import Api
|
|
410
|
+
|
|
411
|
+
api = Api()
|
|
412
|
+
conmon_url = urljoin(api.config["domain"], f"/api/controlImplementation/{control_id}")
|
|
413
|
+
conmon_response = api.get(conmon_url)
|
|
414
|
+
if conmon_response.ok:
|
|
415
|
+
try:
|
|
416
|
+
ctl_imp_json = conmon_response.json()
|
|
417
|
+
return ControlImplementation(**ctl_imp_json)
|
|
418
|
+
except Exception:
|
|
419
|
+
return None
|
|
420
|
+
return None
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def process_implementation(
|
|
424
|
+
ws: Worksheet, control: ControlImportMeta, control_imp: ControlImplementation, custom_fields: list
|
|
425
|
+
) -> None:
|
|
426
|
+
"""
|
|
427
|
+
Processes the implementation columns in the import.
|
|
428
|
+
|
|
429
|
+
:param Worksheet ws:
|
|
430
|
+
:param ControlImportMeta control:
|
|
431
|
+
:param ControlImplementation control_imp:
|
|
432
|
+
:param list custom_fields:
|
|
433
|
+
:return None:
|
|
434
|
+
:rtype None:
|
|
435
|
+
"""
|
|
436
|
+
# Column E (5) - Implementation Status - Control and Compliance Status
|
|
437
|
+
control_imp.status = slcm_status(ws.cell(row=control.import_row, column=5).value)
|
|
438
|
+
# Column F (6) - Common Control Provider - Responsibility - Custom Field (Common Control Provider)
|
|
439
|
+
# control_imp.responsibility = slcm_responsibility(ws.cell(row=control.import_row, column=6).value)
|
|
440
|
+
set_custom_field_data(
|
|
441
|
+
custom_fields, control_imp.id, "Common Control Provider", ws.cell(row=control.import_row, column=6).value
|
|
442
|
+
)
|
|
443
|
+
# Column G (7) - Security Control Designation - Responsibility
|
|
444
|
+
control_imp.responsibility = slcm_scdesignation(
|
|
445
|
+
ws.cell(row=control.import_row, column=7).value, control_imp.responsibility
|
|
446
|
+
)
|
|
447
|
+
# Column H (8) - Test Method - Control Test Plans - Ignore - Should load the default tests and CCIs
|
|
448
|
+
# Column I (9) - N/A Justification - Exclusion Justification
|
|
449
|
+
control_imp.exclusionJustification = ws.cell(row=control.import_row, column=9).value
|
|
450
|
+
# Column J (10) - Estimated Completion Date - Planned Implementation Date
|
|
451
|
+
control_imp.plannedImplementationDate = ws.cell(row=control.import_row, column=10).value
|
|
452
|
+
# Column K (11) - Implementation Narrative - Steps to Implement
|
|
453
|
+
control_imp.stepsToImplement = ws.cell(row=control.import_row, column=11).value
|
|
454
|
+
# Column L (12) - Responsible Entities - Customer/Cloud Implementation
|
|
455
|
+
entities = ws.cell(row=control.import_row, column=12).value
|
|
456
|
+
if control_imp.responsibility == "Customer":
|
|
457
|
+
control_imp.customerImplementation = entities
|
|
458
|
+
elif control_imp.responsibility == "Provider":
|
|
459
|
+
control_imp.cloudImplementation = entities
|
|
460
|
+
else:
|
|
461
|
+
control_imp.customerImplementation = entities
|
|
462
|
+
control_imp.cloudImplementation = entities
|
|
463
|
+
# Column M (13) - Application Layer - Custom Field (Application Layer)
|
|
464
|
+
set_custom_field_data(
|
|
465
|
+
custom_fields, control_imp.id, "Application Layer", ws.cell(row=control.import_row, column=13).value
|
|
466
|
+
)
|
|
467
|
+
# Column N (14) - Database Layer - Custom Field (Database Layer)
|
|
468
|
+
set_custom_field_data(
|
|
469
|
+
custom_fields, control_imp.id, "Database Layer", ws.cell(row=control.import_row, column=14).value
|
|
470
|
+
)
|
|
471
|
+
# Column O (15) - Operating System Layer - Custom Field (Operating System Layer)
|
|
472
|
+
set_custom_field_data(
|
|
473
|
+
custom_fields, control_imp.id, "Operating System Layer", ws.cell(row=control.import_row, column=15).value
|
|
474
|
+
)
|
|
475
|
+
save_control_implementation_update(control_imp)
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
def set_custom_field_data(custom_fields: list, control_id: int, field_name: str, field_value: str) -> None:
|
|
479
|
+
"""
|
|
480
|
+
Creates a custom field data object
|
|
481
|
+
|
|
482
|
+
:param list custom_fields:
|
|
483
|
+
:param int control_id:
|
|
484
|
+
:param str field_name:
|
|
485
|
+
:param str field_value:
|
|
486
|
+
:return None:
|
|
487
|
+
:rtype None:
|
|
488
|
+
"""
|
|
489
|
+
from regscale.core.app.api import Api
|
|
490
|
+
|
|
491
|
+
api = Api()
|
|
492
|
+
if (field_value is None) or (len(field_value) == 0):
|
|
493
|
+
return
|
|
494
|
+
custom_field_rec = find_custom_field(custom_fields, field_name)
|
|
495
|
+
if custom_field_rec is None:
|
|
496
|
+
return
|
|
497
|
+
cfdata = CustomFieldsData()
|
|
498
|
+
cfdata.moduleId = custom_field_rec["moduleId"]
|
|
499
|
+
cfdata.fieldId = custom_field_rec["id"]
|
|
500
|
+
cfdata.fieldName = custom_field_rec["fieldName"]
|
|
501
|
+
cfdata.fieldDataType = custom_field_rec["fieldDataType"]
|
|
502
|
+
cfdata.fieldValue = field_value
|
|
503
|
+
cfdata.parentId = control_id
|
|
504
|
+
cfdata_payload = cfdata.dict()
|
|
505
|
+
conmon_url = urljoin(api.config["domain"], "/api/customFieldsData/")
|
|
506
|
+
conmon_response = api.post(conmon_url, json=cfdata_payload)
|
|
507
|
+
if not conmon_response.ok:
|
|
508
|
+
logger.error(conmon_response)
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
def find_custom_field(custom_fields: list, field_name: str) -> Optional[dict]:
|
|
512
|
+
"""
|
|
513
|
+
Find the appropriate custom field in the list of existing custom fields
|
|
514
|
+
|
|
515
|
+
:param list custom_fields:
|
|
516
|
+
:param str field_name:
|
|
517
|
+
:return dict:
|
|
518
|
+
:rtype dict:
|
|
519
|
+
"""
|
|
520
|
+
for cur_custom_field in custom_fields:
|
|
521
|
+
if cur_custom_field["fieldName"] == field_name:
|
|
522
|
+
return cur_custom_field
|
|
523
|
+
return None
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
def slcm_status(status: str) -> str:
|
|
527
|
+
"""
|
|
528
|
+
Convert the status from the import to the appropriate RS value
|
|
529
|
+
|
|
530
|
+
:param str status:
|
|
531
|
+
:return str:
|
|
532
|
+
:rtype str:
|
|
533
|
+
"""
|
|
534
|
+
if status == "Implemented":
|
|
535
|
+
return "Fully Implemented"
|
|
536
|
+
if (status == "Not Implemented") or (status == "Planned") or (status == "Inherited"):
|
|
537
|
+
return status
|
|
538
|
+
return NOT_APPLICABLE
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
def slcm_responsibility(responsibility: str) -> str:
|
|
542
|
+
"""
|
|
543
|
+
Convert the responsibility from the import to the appropriate RS value
|
|
544
|
+
|
|
545
|
+
:param str responsibility:
|
|
546
|
+
:return str:
|
|
547
|
+
:rtype str:
|
|
548
|
+
"""
|
|
549
|
+
if responsibility == "DoD":
|
|
550
|
+
return "Customer"
|
|
551
|
+
if responsibility == "Component":
|
|
552
|
+
return "Provider"
|
|
553
|
+
if responsibility == "Enclave":
|
|
554
|
+
return "Shared"
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
def slcm_scdesignation(scdesignation: str, responsibility: str) -> str:
|
|
558
|
+
"""
|
|
559
|
+
Convert the SLCM designation from the import to the appropriate RS value
|
|
560
|
+
|
|
561
|
+
:param str scdesignation:
|
|
562
|
+
:param str responsibility:
|
|
563
|
+
:return str:
|
|
564
|
+
:rtype str:
|
|
565
|
+
"""
|
|
566
|
+
if scdesignation == "Hybrid":
|
|
567
|
+
return "Hybrid"
|
|
568
|
+
return responsibility
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
def process_slcm(
|
|
572
|
+
ws: Worksheet, control: ControlImportMeta, control_imp: ControlImplementation, custom_fields: list
|
|
573
|
+
) -> None:
|
|
574
|
+
"""
|
|
575
|
+
Process the SLCM columns of the import
|
|
576
|
+
|
|
577
|
+
:param Worksheet ws:
|
|
578
|
+
:param ControlImportMeta control:
|
|
579
|
+
:param ControlImplementation control_imp:
|
|
580
|
+
:param list custom_fields:
|
|
581
|
+
:return None:
|
|
582
|
+
:rtype None:
|
|
583
|
+
"""
|
|
584
|
+
# Column Q (17) - Criticality - Ignore - Leaving blank in the export
|
|
585
|
+
# Column R (18) - Frequency
|
|
586
|
+
control_imp.assessmentFrequency = slcm_frequency_calculation(ws.cell(row=control.import_row, column=18).value)
|
|
587
|
+
# Column S (19) - Method - Custom Field (Method)
|
|
588
|
+
set_custom_field_data(custom_fields, control_imp.id, "Method", ws.cell(row=control.import_row, column=19).value)
|
|
589
|
+
# Column T (20) - Reporting - Ignore - Statement built based on whether control has CCI's and ConMon
|
|
590
|
+
# Column U (21) - Tracking - Ignore - Statement built based on whether control has CCI's
|
|
591
|
+
# Column V (22) - SLCM Comments - Assessments
|
|
592
|
+
save_control_implementation_update(control_imp)
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
def slcm_frequency_calculation(frequency: str) -> int:
|
|
596
|
+
"""
|
|
597
|
+
Convert the SLCM frequency to a RS frequency in days.
|
|
598
|
+
|
|
599
|
+
:param str frequency:
|
|
600
|
+
:return int:
|
|
601
|
+
:rtype int:
|
|
602
|
+
"""
|
|
603
|
+
if frequency == "Every Three Years":
|
|
604
|
+
return 365 * 3
|
|
605
|
+
if frequency == "Every Two Years":
|
|
606
|
+
return 365 * 2
|
|
607
|
+
if frequency == "Annually":
|
|
608
|
+
return 365
|
|
609
|
+
if frequency == "Semi-annually":
|
|
610
|
+
return 163
|
|
611
|
+
if frequency == "Quarterly":
|
|
612
|
+
return 90
|
|
613
|
+
if frequency == "Monthly":
|
|
614
|
+
return 30
|
|
615
|
+
if frequency == "Weekly":
|
|
616
|
+
return 7
|
|
617
|
+
return 1
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
def process_risk_assessment(
|
|
621
|
+
ws: Worksheet, control: ControlImportMeta, regscale_id: int, control_imp: ControlImplementation
|
|
622
|
+
) -> None:
|
|
623
|
+
"""
|
|
624
|
+
Process the Risk Assessment columns of the import - These are calculated values in the export,
|
|
625
|
+
and thus are not included in the import (at this time).
|
|
626
|
+
|
|
627
|
+
:param Worksheet ws:
|
|
628
|
+
:param ControlImportMeta control:
|
|
629
|
+
:param int regscale_id:
|
|
630
|
+
:param ControlImplementation control_imp:
|
|
631
|
+
:return None:
|
|
632
|
+
:rtype None:
|
|
633
|
+
"""
|
|
634
|
+
# This whole section goes to Mitigations and Risks - Ignore - These don't have the key information needed to create
|
|
635
|
+
# Column X (24) - Severity - Risk - Consequence
|
|
636
|
+
# Column Y (25) - Relevance of Threat - Risk - Probability
|
|
637
|
+
# Column Z (26) - Likelihood - Calculated from Consequence and Probability - Leave for now
|
|
638
|
+
# Column AA (27) - Impact - Risk - Spread across all Risk fields
|
|
639
|
+
# Column AB (28) - Residual Risk Level - Calculated - Leave for now
|
|
640
|
+
# Column AC (29) - Vulnerability Summary - Risk - RiskStatement
|
|
641
|
+
# Column AD (30) - Mitigations - Risk - Mitigation
|
|
642
|
+
# Column AE (31) - Impact Description - Risk - ImpactDescription
|
|
643
|
+
# Column AF (32) - Recommendations - RiskTreatments (tied to Risk.id)
|
|
644
|
+
if (ws is None) or (control is None) or (regscale_id <= 0) or (control_imp is None):
|
|
645
|
+
logger.warning("Processing Risk Assessment - No data to import")
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
def verify_sp_id(regscale_id: int) -> bool:
|
|
649
|
+
"""
|
|
650
|
+
Verify the provided SP ID is valid
|
|
651
|
+
|
|
652
|
+
:param int regscale_id:
|
|
653
|
+
:return bool:
|
|
654
|
+
:rtype bool:
|
|
655
|
+
"""
|
|
656
|
+
from regscale.core.app.api import Api
|
|
657
|
+
|
|
658
|
+
api = Api()
|
|
659
|
+
sp = SecurityPlan.get_object(regscale_id)
|
|
660
|
+
if sp is None:
|
|
661
|
+
logger.warning("Model didn't return any security plan, trying again with the REST API")
|
|
662
|
+
conmon_url = urljoin(api.config["domain"], f"/api/securityplans/{regscale_id}")
|
|
663
|
+
conmon_response = api.get(conmon_url)
|
|
664
|
+
if conmon_response.ok:
|
|
665
|
+
try:
|
|
666
|
+
sec_plan = conmon_response.json()
|
|
667
|
+
if sec_plan is None:
|
|
668
|
+
return False
|
|
669
|
+
except Exception:
|
|
670
|
+
return False
|
|
671
|
+
return True
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
def verify_cat_id(catalogue_id: int) -> bool:
|
|
675
|
+
"""
|
|
676
|
+
Verify the provided catalog ID is valid
|
|
677
|
+
|
|
678
|
+
:param int catalogue_id:
|
|
679
|
+
:return bool:
|
|
680
|
+
:rtype bool:
|
|
681
|
+
"""
|
|
682
|
+
from regscale.core.app.api import Api
|
|
683
|
+
|
|
684
|
+
api = Api()
|
|
685
|
+
sp = Catalog.get_object(catalogue_id)
|
|
686
|
+
if sp is None:
|
|
687
|
+
logger.warning("Model didn't return any catalog, trying again with the REST API")
|
|
688
|
+
conmon_url = urljoin(api.config["domain"], f"/api/catalog/{catalogue_id}")
|
|
689
|
+
conmon_response = api.get(conmon_url)
|
|
690
|
+
if conmon_response.ok:
|
|
691
|
+
try:
|
|
692
|
+
sec_plan = conmon_response.json()
|
|
693
|
+
if sec_plan is None:
|
|
694
|
+
return False
|
|
695
|
+
except Exception:
|
|
696
|
+
return False
|
|
697
|
+
return True
|
|
File without changes
|