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,571 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Module to allow user to make changes to Control Implementations in an Excel spreadsheet for a user-friendly experience
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import math
|
|
8
|
+
import os
|
|
9
|
+
import shutil
|
|
10
|
+
import sys
|
|
11
|
+
from typing import Union, Any, TYPE_CHECKING
|
|
12
|
+
|
|
13
|
+
import click
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from regscale.core.app.api import Api
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
from openpyxl import Workbook, load_workbook
|
|
21
|
+
from openpyxl.styles import Alignment, PatternFill, Protection
|
|
22
|
+
from openpyxl.worksheet.datavalidation import DataValidation
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
from regscale.core.app.logz import create_logger
|
|
26
|
+
from regscale.core.app.utils.app_utils import (
|
|
27
|
+
check_empty_nan,
|
|
28
|
+
check_file_path,
|
|
29
|
+
error_and_exit,
|
|
30
|
+
get_current_datetime,
|
|
31
|
+
get_user_names,
|
|
32
|
+
)
|
|
33
|
+
from regscale.models.app_models.click import regscale_id, regscale_module
|
|
34
|
+
from regscale.models.regscale_models.control import Control
|
|
35
|
+
from regscale.models.regscale_models.control_implementation import ControlImplementation
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
ALL_IMPS = "all_implementations.xlsx"
|
|
39
|
+
OLD_IMPS = "old_implementations.xlsx"
|
|
40
|
+
DIFFS = "differences.txt"
|
|
41
|
+
ERROR_MSG = "Your entry is not one of the available options"
|
|
42
|
+
INVALID_MSG = "Invalid Entry"
|
|
43
|
+
PROMPT_MSG = "Please select from the list"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@click.group(name="control_editor")
|
|
47
|
+
def control_editor():
|
|
48
|
+
"""
|
|
49
|
+
Performs actions on Control Editor Feature to edit controls to RegScale.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# Get data and pull into Excel worksheets.
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@control_editor.command(name="generate")
|
|
57
|
+
@regscale_id()
|
|
58
|
+
@regscale_module()
|
|
59
|
+
@click.option(
|
|
60
|
+
"--path",
|
|
61
|
+
type=click.Path(exists=False, dir_okay=True, path_type=Path),
|
|
62
|
+
help="Provide the desired path for created excel files to be saved to.",
|
|
63
|
+
default=Path("./artifacts"),
|
|
64
|
+
required=True,
|
|
65
|
+
)
|
|
66
|
+
def generate_data_download(regscale_id: int, regscale_module: str, path: Path):
|
|
67
|
+
"""
|
|
68
|
+
This function will build and populate a spreadsheet of all control implementations
|
|
69
|
+
with the selected RegScale Parent Id and RegScale Module.
|
|
70
|
+
"""
|
|
71
|
+
data_load(parent_id=regscale_id, parent_module=regscale_module, path=path)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def data_load(parent_id: int, parent_module: str, path: Path) -> None:
|
|
75
|
+
"""Function takes organizer record and module and build excel worksheet of control implementations.
|
|
76
|
+
|
|
77
|
+
:param int parent_id: RegScale Parent Id
|
|
78
|
+
:param str parent_module: RegScale Parent Module
|
|
79
|
+
:param Path path: directory of file location
|
|
80
|
+
:rtype: None
|
|
81
|
+
"""
|
|
82
|
+
import pandas as pd # Optimize import performance
|
|
83
|
+
from regscale.core.app.api import Api
|
|
84
|
+
|
|
85
|
+
api = Api()
|
|
86
|
+
logger = api.logger
|
|
87
|
+
all_imps_wb = path / ALL_IMPS
|
|
88
|
+
old_imps_wb = path / OLD_IMPS
|
|
89
|
+
|
|
90
|
+
# Making directory for files
|
|
91
|
+
|
|
92
|
+
check_file_path(path)
|
|
93
|
+
|
|
94
|
+
workbook = Workbook()
|
|
95
|
+
ws = workbook.active
|
|
96
|
+
ws.title = f"Impls_PId({parent_id}_{parent_module})"
|
|
97
|
+
workbook.create_sheet("Accounts")
|
|
98
|
+
|
|
99
|
+
workbook.save(filename=all_imps_wb)
|
|
100
|
+
shutil.copy(
|
|
101
|
+
all_imps_wb,
|
|
102
|
+
old_imps_wb,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Loading data from RegScale database into two workbooks.
|
|
106
|
+
|
|
107
|
+
all_imps_df = _fetch_implementations(api, parent_id, parent_module)
|
|
108
|
+
|
|
109
|
+
with pd.ExcelWriter(
|
|
110
|
+
all_imps_wb,
|
|
111
|
+
mode="a",
|
|
112
|
+
engine="openpyxl",
|
|
113
|
+
if_sheet_exists="overlay",
|
|
114
|
+
) as writer:
|
|
115
|
+
all_imps_df.to_excel(
|
|
116
|
+
writer,
|
|
117
|
+
sheet_name=f"Impls_PId({parent_id}_{parent_module})",
|
|
118
|
+
index=False,
|
|
119
|
+
)
|
|
120
|
+
get_user_names().to_excel(
|
|
121
|
+
writer,
|
|
122
|
+
sheet_name="Accounts",
|
|
123
|
+
index=False,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
with pd.ExcelWriter(
|
|
127
|
+
old_imps_wb,
|
|
128
|
+
mode="a",
|
|
129
|
+
engine="openpyxl",
|
|
130
|
+
if_sheet_exists="overlay",
|
|
131
|
+
) as writer:
|
|
132
|
+
all_imps_df.to_excel(
|
|
133
|
+
writer,
|
|
134
|
+
sheet_name=f"Impls_PId({parent_id}_{parent_module})",
|
|
135
|
+
index=False,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
# Adding Data validation to "old_implementations.xlsx" file that will be used as reference.
|
|
139
|
+
|
|
140
|
+
workbook2 = load_workbook(old_imps_wb)
|
|
141
|
+
worksheet2 = workbook2.active
|
|
142
|
+
worksheet2.protection.sheet = True
|
|
143
|
+
workbook2.save(filename=old_imps_wb)
|
|
144
|
+
|
|
145
|
+
# Adding Data Validation to "all_implementations.xlsx" file to be adjusted internally by clients.
|
|
146
|
+
|
|
147
|
+
workbook = load_workbook(all_imps_wb)
|
|
148
|
+
worksheet = workbook.active
|
|
149
|
+
worksheet.protection.sheet = True
|
|
150
|
+
accounts_worksheet = workbook["Accounts"]
|
|
151
|
+
accounts_worksheet.protection.sheet = True
|
|
152
|
+
|
|
153
|
+
dv1 = DataValidation(
|
|
154
|
+
type="list",
|
|
155
|
+
formula1='"Not Implemented, Fully Implemented, In Remediation, Not Applicable, Inherited, Planned"',
|
|
156
|
+
allow_blank=True,
|
|
157
|
+
showDropDown=False,
|
|
158
|
+
error=ERROR_MSG,
|
|
159
|
+
errorTitle=INVALID_MSG,
|
|
160
|
+
prompt=PROMPT_MSG,
|
|
161
|
+
)
|
|
162
|
+
dv2 = DataValidation(
|
|
163
|
+
type="list",
|
|
164
|
+
formula1='"Provider, Customer, Shared, Not Applicable"',
|
|
165
|
+
allow_blank=True,
|
|
166
|
+
showDropDown=False,
|
|
167
|
+
error=ERROR_MSG,
|
|
168
|
+
errorTitle=INVALID_MSG,
|
|
169
|
+
prompt=PROMPT_MSG,
|
|
170
|
+
)
|
|
171
|
+
dv3 = DataValidation(type="list", formula1='"TRUE, FALSE"', allow_blank=True)
|
|
172
|
+
dv4 = DataValidation(
|
|
173
|
+
type="list",
|
|
174
|
+
formula1="=Accounts!$A$2:$A$" + str(get_maximum_rows(sheet_object=workbook["Accounts"])),
|
|
175
|
+
allow_blank=False,
|
|
176
|
+
showDropDown=False,
|
|
177
|
+
error=ERROR_MSG,
|
|
178
|
+
errorTitle=INVALID_MSG,
|
|
179
|
+
prompt=PROMPT_MSG,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
worksheet.add_data_validation(dv1)
|
|
183
|
+
worksheet.add_data_validation(dv2)
|
|
184
|
+
worksheet.add_data_validation(dv3)
|
|
185
|
+
worksheet.add_data_validation(dv4)
|
|
186
|
+
dv1.add("G2:G1048576")
|
|
187
|
+
dv2.add("J2:J1048576")
|
|
188
|
+
dv3.add("K2:K1048576")
|
|
189
|
+
dv4.add("C2:C1048576")
|
|
190
|
+
|
|
191
|
+
for col in worksheet.columns:
|
|
192
|
+
max_length = 0
|
|
193
|
+
column = col[0].column_letter # Get the column name
|
|
194
|
+
for cell in col:
|
|
195
|
+
if len(str(cell.value)) > max_length:
|
|
196
|
+
max_length = len(str(cell.value))
|
|
197
|
+
|
|
198
|
+
adjusted_width = (max_length + 2) * 1.2
|
|
199
|
+
if adjusted_width < 50:
|
|
200
|
+
worksheet.column_dimensions[column].width = adjusted_width
|
|
201
|
+
else:
|
|
202
|
+
worksheet.column_dimensions[column].width = 50
|
|
203
|
+
check_and_format_cells(column, col)
|
|
204
|
+
|
|
205
|
+
workbook.save(filename=all_imps_wb)
|
|
206
|
+
|
|
207
|
+
logger.info("Successfully created the directory %s.", path)
|
|
208
|
+
logger.info("All files are located within directory.")
|
|
209
|
+
|
|
210
|
+
logger.info(
|
|
211
|
+
"Your data has been loaded into your excel workbook. "
|
|
212
|
+
"Please open the all_implementations workbook and make your desired changes."
|
|
213
|
+
)
|
|
214
|
+
return None
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def check_and_format_cells(column: str, col: list[Any]) -> None:
|
|
218
|
+
"""
|
|
219
|
+
Function to align cells in the provided column
|
|
220
|
+
|
|
221
|
+
:param str column: Column to align
|
|
222
|
+
:param list[Any] col: Column to align
|
|
223
|
+
:rtype: None
|
|
224
|
+
"""
|
|
225
|
+
if column in [
|
|
226
|
+
"E",
|
|
227
|
+
"F",
|
|
228
|
+
"I",
|
|
229
|
+
]:
|
|
230
|
+
for cell in col:
|
|
231
|
+
cell.alignment = Alignment(wrap_text=True)
|
|
232
|
+
|
|
233
|
+
if column in [
|
|
234
|
+
"C",
|
|
235
|
+
"G",
|
|
236
|
+
"H",
|
|
237
|
+
"I",
|
|
238
|
+
"J",
|
|
239
|
+
"K",
|
|
240
|
+
]: # Check if current column is column to edit
|
|
241
|
+
for cell in col:
|
|
242
|
+
cell.fill = PatternFill(start_color="7C7C7C", end_color="7C7C7C", fill_type="solid")
|
|
243
|
+
cell.protection = Protection(locked=False) # Unprotect the cell
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def _fetch_implementations(api: "Api", parent_id: int, parent_module: str) -> "pd.DataFrame":
|
|
247
|
+
"""
|
|
248
|
+
Function to fetch implementations from RegScale.
|
|
249
|
+
|
|
250
|
+
:param Api api: API object to make calls to RegScale
|
|
251
|
+
:param int parent_id: Parent ID of the implementation in RegScale
|
|
252
|
+
:param str parent_module: Parent module of the implementation in RegScale
|
|
253
|
+
:return: DataFrame of implementations
|
|
254
|
+
:rtype: pd.DataFrame
|
|
255
|
+
"""
|
|
256
|
+
import pandas as pd # Optimize import performance
|
|
257
|
+
|
|
258
|
+
body = f"""
|
|
259
|
+
query {{
|
|
260
|
+
controlImplementations(
|
|
261
|
+
skip: 0
|
|
262
|
+
take: 50
|
|
263
|
+
where: {{
|
|
264
|
+
parentId: {{ eq: {parent_id} }}
|
|
265
|
+
parentModule: {{ eq: "{parent_module}" }}
|
|
266
|
+
}}
|
|
267
|
+
) {{
|
|
268
|
+
items {{
|
|
269
|
+
id
|
|
270
|
+
controlID
|
|
271
|
+
controlOwner {{
|
|
272
|
+
firstName
|
|
273
|
+
lastName
|
|
274
|
+
userName
|
|
275
|
+
}}
|
|
276
|
+
control {{
|
|
277
|
+
title
|
|
278
|
+
description
|
|
279
|
+
controlId
|
|
280
|
+
weight
|
|
281
|
+
catalogueID
|
|
282
|
+
}}
|
|
283
|
+
status
|
|
284
|
+
policy
|
|
285
|
+
implementation
|
|
286
|
+
responsibility
|
|
287
|
+
inheritable
|
|
288
|
+
parentId
|
|
289
|
+
parentModule
|
|
290
|
+
}}
|
|
291
|
+
totalCount
|
|
292
|
+
pageInfo {{
|
|
293
|
+
hasNextPage
|
|
294
|
+
}}
|
|
295
|
+
}}
|
|
296
|
+
}}
|
|
297
|
+
"""
|
|
298
|
+
existing_implementation_data = api.graph(query=body)
|
|
299
|
+
|
|
300
|
+
if existing_implementation_data["controlImplementations"]["totalCount"] <= 0:
|
|
301
|
+
error_and_exit("No records exist for the given RegScale Id and RegScale Module.")
|
|
302
|
+
|
|
303
|
+
all_imps = [
|
|
304
|
+
[
|
|
305
|
+
item["id"],
|
|
306
|
+
item["controlID"],
|
|
307
|
+
f'{str(item["controlOwner"]["lastName"]).strip()}, {str(item["controlOwner"]["firstName"]).strip()} '
|
|
308
|
+
+ f'({str(item["controlOwner"]["userName"]).strip()})',
|
|
309
|
+
item["control"]["controlId"],
|
|
310
|
+
item["control"]["title"],
|
|
311
|
+
item["control"]["description"],
|
|
312
|
+
item["status"],
|
|
313
|
+
item["policy"],
|
|
314
|
+
item["implementation"],
|
|
315
|
+
item["responsibility"],
|
|
316
|
+
item["inheritable"],
|
|
317
|
+
item["control"]["weight"],
|
|
318
|
+
item["control"]["catalogueID"],
|
|
319
|
+
]
|
|
320
|
+
for item in existing_implementation_data.get("controlImplementations", {}).get("items", [])
|
|
321
|
+
]
|
|
322
|
+
|
|
323
|
+
all_imps_df = pd.DataFrame(
|
|
324
|
+
all_imps,
|
|
325
|
+
columns=[
|
|
326
|
+
"Id",
|
|
327
|
+
"ControlId",
|
|
328
|
+
"ControlOwner",
|
|
329
|
+
"ControlName",
|
|
330
|
+
"ControlTitle",
|
|
331
|
+
"Description",
|
|
332
|
+
"Status",
|
|
333
|
+
"Policy",
|
|
334
|
+
"Implementation",
|
|
335
|
+
"Responsibility",
|
|
336
|
+
"Inheritable",
|
|
337
|
+
"Weight",
|
|
338
|
+
"CatalogueId",
|
|
339
|
+
],
|
|
340
|
+
)
|
|
341
|
+
return all_imps_df
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
@control_editor.command(name="load")
|
|
345
|
+
@click.option(
|
|
346
|
+
"--path",
|
|
347
|
+
type=click.Path(exists=False, dir_okay=True, path_type=Path),
|
|
348
|
+
help="Provide the desired path where excel workbooks are located.",
|
|
349
|
+
default=Path("./artifacts"),
|
|
350
|
+
required=True,
|
|
351
|
+
)
|
|
352
|
+
@click.option(
|
|
353
|
+
"--skip_prompt",
|
|
354
|
+
type=click.BOOL,
|
|
355
|
+
help="To Skip (Y/N) Prompt, input True.",
|
|
356
|
+
default=False,
|
|
357
|
+
required=False,
|
|
358
|
+
)
|
|
359
|
+
def generate_db_update(path: Path, skip_prompt: bool):
|
|
360
|
+
"""
|
|
361
|
+
This function will check changes made to spreadsheet and upload any changes made to RegScale.
|
|
362
|
+
|
|
363
|
+
"""
|
|
364
|
+
db_update(path, skip_prompt)
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def db_update(path: Path, skip_prompt: bool = True) -> None:
|
|
368
|
+
"""Function will check changes made by user and upload any changes to RegScale.
|
|
369
|
+
|
|
370
|
+
:param Path path: directory of file location
|
|
371
|
+
:param bool skip_prompt: boolean to skip prompt save message, defaults to True
|
|
372
|
+
:rtype: None
|
|
373
|
+
"""
|
|
374
|
+
import pandas as pd # Optimize import performance
|
|
375
|
+
import numpy as np # Optimize import performance
|
|
376
|
+
|
|
377
|
+
logger = create_logger()
|
|
378
|
+
all_imps_wb = path / ALL_IMPS
|
|
379
|
+
old_imps_wb = path / OLD_IMPS
|
|
380
|
+
regscale_parent_id = None
|
|
381
|
+
regscale_parent_module = None
|
|
382
|
+
|
|
383
|
+
logger.info("Proceed only after you have made the necessary changes and have saved file.")
|
|
384
|
+
|
|
385
|
+
x = "y" if skip_prompt else input("Ready to Proceed (Y/N): ").lower()
|
|
386
|
+
|
|
387
|
+
if x[0] == "y":
|
|
388
|
+
file_path = all_imps_wb
|
|
389
|
+
if not os.path.exists(file_path):
|
|
390
|
+
error_and_exit(f"Unable to locate the file {file_path}.")
|
|
391
|
+
|
|
392
|
+
df = load_workbook(file_path)
|
|
393
|
+
|
|
394
|
+
sheet_name = df.sheetnames[0]
|
|
395
|
+
sheet_name = sheet_name[sheet_name.find("(") + 1 : sheet_name.find(")")].split("_")
|
|
396
|
+
# set the variables to the correct values
|
|
397
|
+
for item in set(sheet_name):
|
|
398
|
+
try:
|
|
399
|
+
regscale_parent_id = int(item)
|
|
400
|
+
except ValueError:
|
|
401
|
+
regscale_parent_module = item
|
|
402
|
+
if not regscale_parent_id or not regscale_parent_module:
|
|
403
|
+
error_and_exit("Unable to locate the RegScale Parent ID and RegScale Parent Module.")
|
|
404
|
+
|
|
405
|
+
df1 = pd.read_excel(all_imps_wb, sheet_name=0, index_col="Id")
|
|
406
|
+
|
|
407
|
+
df2 = pd.read_excel(old_imps_wb, sheet_name=0, index_col="Id")
|
|
408
|
+
|
|
409
|
+
if df1.equals(df2):
|
|
410
|
+
logger.warning("No differences detected.")
|
|
411
|
+
sys.exit(0)
|
|
412
|
+
|
|
413
|
+
else:
|
|
414
|
+
logger.warning("*** WARNING *** Differences Found.")
|
|
415
|
+
|
|
416
|
+
# Logs changes to txt file
|
|
417
|
+
|
|
418
|
+
diff_mask = (df1 != df2) & ~(df1.isnull() & df2.isnull())
|
|
419
|
+
ne_stacked = diff_mask.stack()
|
|
420
|
+
changed = ne_stacked[ne_stacked]
|
|
421
|
+
changed.index.names = ["Id", "Column"]
|
|
422
|
+
difference_locations = np.nonzero(diff_mask)
|
|
423
|
+
changed_to = df1.values[difference_locations]
|
|
424
|
+
changed_from = df2.values[difference_locations]
|
|
425
|
+
changes = pd.DataFrame({"From": changed_from, "To": changed_to}, index=changed.index)
|
|
426
|
+
changes.to_csv(
|
|
427
|
+
path / DIFFS,
|
|
428
|
+
header=True,
|
|
429
|
+
index=True,
|
|
430
|
+
sep=" ",
|
|
431
|
+
mode="a",
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
upload_data(regscale_parent_id, regscale_parent_module, path)
|
|
435
|
+
|
|
436
|
+
logger.info("Please check differences.txt file located in artifacts folder to see changes made.")
|
|
437
|
+
return None
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def upload_data(regscale_parent_id: int, regscale_parent_module: str, path: Path) -> None:
|
|
441
|
+
"""
|
|
442
|
+
Batch uploads updated control implementation statements to the provided RegScale parent ID.
|
|
443
|
+
|
|
444
|
+
:param int regscale_parent_id: RegScale parent ID
|
|
445
|
+
:param str regscale_parent_module: RegScale parent module
|
|
446
|
+
:param Path path: file path where control spreadsheet resides
|
|
447
|
+
:rtype: None
|
|
448
|
+
"""
|
|
449
|
+
import pandas as pd # Optimize import performance
|
|
450
|
+
|
|
451
|
+
diff = pd.read_csv(path / DIFFS, header=0, sep=" ", index_col=None)
|
|
452
|
+
ids = []
|
|
453
|
+
for i, row in diff.iterrows():
|
|
454
|
+
ids.append(row["Id"])
|
|
455
|
+
|
|
456
|
+
id_df = pd.DataFrame(ids, index=None, columns=["Id"])
|
|
457
|
+
id_df2 = id_df.drop_duplicates()
|
|
458
|
+
|
|
459
|
+
reader = pd.read_excel(path / ALL_IMPS)
|
|
460
|
+
accounts = pd.read_excel(path / ALL_IMPS, sheet_name="Accounts")
|
|
461
|
+
accounts = accounts.rename(columns={"User": "ControlOwner", "UserId": "ControlOwnerId"})
|
|
462
|
+
|
|
463
|
+
updates = reader[reader["Id"].isin(id_df2["Id"])]
|
|
464
|
+
updates = updates.merge(accounts, how="left", on="ControlOwner")
|
|
465
|
+
updates = updates.T.to_dict()
|
|
466
|
+
|
|
467
|
+
_ = [build_implementation(i, regscale_parent_id, regscale_parent_module) for i in updates.values()]
|
|
468
|
+
|
|
469
|
+
ControlImplementation.bulk_save()
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
def build_implementation(i: dict, regscale_parent_id: int, regscale_parent_module: str) -> ControlImplementation:
|
|
473
|
+
"""
|
|
474
|
+
Builds a ControlImplementation object from a dictionary
|
|
475
|
+
|
|
476
|
+
:param dict i: dictionary of control implementation
|
|
477
|
+
:param int regscale_parent_id: RegScale parent ID
|
|
478
|
+
:param str regscale_parent_module: RegScale parent module
|
|
479
|
+
:return: ControlImplementation object
|
|
480
|
+
:rtype: ControlImplementation
|
|
481
|
+
"""
|
|
482
|
+
control = Control(
|
|
483
|
+
title=i["ControlTitle"],
|
|
484
|
+
description=i["Description"],
|
|
485
|
+
controlId=i["ControlName"],
|
|
486
|
+
weight=i["Weight"],
|
|
487
|
+
catalogueID=i["CatalogueId"],
|
|
488
|
+
)
|
|
489
|
+
control_implementation = ControlImplementation(
|
|
490
|
+
id=i["Id"],
|
|
491
|
+
controlOwnerId=i["ControlOwnerId"],
|
|
492
|
+
control=control.dict(),
|
|
493
|
+
status=i["Status"],
|
|
494
|
+
implementation=check_empty_nan(i["Implementation"]),
|
|
495
|
+
policy=check_empty_nan(i["Policy"]),
|
|
496
|
+
controlID=i["ControlId"],
|
|
497
|
+
responsibility=check_empty_nan(i["Responsibility"]),
|
|
498
|
+
parentId=regscale_parent_id,
|
|
499
|
+
parentModule=regscale_parent_module,
|
|
500
|
+
inheritable=check_inheritable(i["Inheritable"]),
|
|
501
|
+
dateLastUpdated=get_current_datetime(),
|
|
502
|
+
)
|
|
503
|
+
return control_implementation.save(bulk=True)
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
# Delete and remove files from user's system.
|
|
507
|
+
@control_editor.command(name="delete_files")
|
|
508
|
+
@click.option(
|
|
509
|
+
"--path",
|
|
510
|
+
type=click.Path(exists=False, dir_okay=True, path_type=Path),
|
|
511
|
+
help="Provide the desired path of file location.",
|
|
512
|
+
default=Path("./artifacts"),
|
|
513
|
+
required=True,
|
|
514
|
+
)
|
|
515
|
+
def generate_delete_file(path: Path):
|
|
516
|
+
"""This command will delete files used during the Control editing process."""
|
|
517
|
+
delete_file(path)
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
def delete_file(path: Path) -> int:
|
|
521
|
+
"""
|
|
522
|
+
Deletes files used during the process
|
|
523
|
+
|
|
524
|
+
:param Path path: directory of file location
|
|
525
|
+
:return: Number of files deleted
|
|
526
|
+
:rtype: int
|
|
527
|
+
"""
|
|
528
|
+
logger = create_logger()
|
|
529
|
+
file_names = [
|
|
530
|
+
ALL_IMPS,
|
|
531
|
+
OLD_IMPS,
|
|
532
|
+
DIFFS,
|
|
533
|
+
]
|
|
534
|
+
deleted_files = []
|
|
535
|
+
|
|
536
|
+
for file_name in file_names:
|
|
537
|
+
if os.path.isfile(path / file_name):
|
|
538
|
+
os.remove(path / file_name)
|
|
539
|
+
deleted_files.append(file_name)
|
|
540
|
+
else:
|
|
541
|
+
logger.warning("No %s file found. Checking for other files before exiting.", file_name)
|
|
542
|
+
logger.info("%i files have been deleted: %s", len(deleted_files), ", ".join(deleted_files))
|
|
543
|
+
return len(deleted_files)
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
def check_inheritable(
|
|
547
|
+
value: Any,
|
|
548
|
+
) -> Union[
|
|
549
|
+
str, float, bool
|
|
550
|
+
]: # this function has to be checked separate to account for API only accepting False Boolean unlike other class params
|
|
551
|
+
"""This function takes a given value for an inheritable and checks if value is empty or NaN based on value type.
|
|
552
|
+
|
|
553
|
+
:param Any value: A string or float object
|
|
554
|
+
:return: A string value, float value or False
|
|
555
|
+
:rtype: Union[str, float, bool]
|
|
556
|
+
"""
|
|
557
|
+
if isinstance(value, str) and value.strip() == "":
|
|
558
|
+
return False
|
|
559
|
+
if isinstance(value, float) and math.isnan(value):
|
|
560
|
+
return False
|
|
561
|
+
return value
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
def get_maximum_rows(*, sheet_object: Any) -> int:
|
|
565
|
+
"""This function finds the last row containing data in a spreadsheet
|
|
566
|
+
|
|
567
|
+
:param Any sheet_object: excel worksheet to be referenced
|
|
568
|
+
:return: integer representing last row with data in spreadsheet
|
|
569
|
+
:rtype: int
|
|
570
|
+
"""
|
|
571
|
+
return sum(any(col.value is not None for col in row) for max_row, row in enumerate(sheet_object, 1))
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# fmt: off
|
|
2
|
+
# flake8: noqa
|
|
3
|
+
#!/usr/bin/env python3
|
|
4
|
+
# -*- coding: utf-8 -*-
|
|
5
|
+
# pylint: disable-all
|
|
6
|
+
|
|
7
|
+
a=' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'
|
|
8
|
+
import base64 as V1R45
|
|
9
|
+
import logging
|
|
10
|
+
import os
|
|
11
|
+
import platform as MJ5112
|
|
12
|
+
import sys
|
|
13
|
+
from getpass import getpass as JL21
|
|
14
|
+
from os.path import exists as LMK849
|
|
15
|
+
|
|
16
|
+
from cryptography.fernet import Fernet as L54SD
|
|
17
|
+
from cryptography.fernet import InvalidToken as EL714DO
|
|
18
|
+
|
|
19
|
+
B=logging.getLogger("regscale")
|
|
20
|
+
D=a[14]+a[83]+a[69]+a[67]+a[82]+a[69]+a[84]+a[83]
|
|
21
|
+
F=a[14]+a[84]+a[88]+a[84],a[14]+a[89]+a[65]+a[77]+a[76],a[14]+a[74]+a[83]+a[79]+a[78],a[14]+a[67]+a[83]+a[86]
|
|
22
|
+
def A7801(a_6451):G6487=V1R45.b64encode(a_6451.encode(a[85]+a[84]+a[70]+a[13]+a[24]));return G6487
|
|
23
|
+
def N4512_3s2(B24156):G4891=V1R45.b64decode(B24156);G4891=G4891.decode(a[85]+a[84]+a[70]+a[13]+a[24]);return G4891
|
|
24
|
+
def G9873():
|
|
25
|
+
if not LMK849(D):
|
|
26
|
+
os.makedirs(D)
|
|
27
|
+
if MJ5112.system().lower()==a[87]+a[73]+a[78]+a[68]+a[79]+a[87]+a[83]:os.system(a[65]+a[84]+a[84]+a[82]+a[73]+a[66]+a[0]+a[11]+a[72]+a[0]+D)
|
|
28
|
+
if LMK849(a[14]+a[15]+D+a[15]+a[70]+a[73]+a[76]+a[69]+a[75]+a[69]+a[89]+a[14]+a[75]+a[69]+a[89]):
|
|
29
|
+
with open(a[14]+a[15]+D+a[15]+a[70]+a[73]+a[76]+a[69]+a[75]+a[69]+a[89]+a[14]+a[75]+a[69]+a[89],a[82]+a[66])as HJ6584:Y8293=HJ6584.read()
|
|
30
|
+
else:
|
|
31
|
+
Y8293=L54SD.generate_key()
|
|
32
|
+
with open(a[14]+a[15]+D+a[15]+a[70]+a[73]+a[76]+a[69]+a[75]+a[69]+a[89]+a[14]+a[75]+a[69]+a[89],a[87]+a[66])as HJ6584:HJ6584.write(Y8293)
|
|
33
|
+
return Y8293
|
|
34
|
+
def AB53621(JT3828):
|
|
35
|
+
a9531=JL21(a[48]+a[76]+a[69]+a[65]+a[83]+a[69]+a[0]+a[67]+a[82]+a[69]+a[65]+a[84]+a[69]+a[0]+a[48]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[26]+a[0]);TH4874=JL21(a[48]+a[76]+a[69]+a[65]+a[83]+a[69]+a[0]+a[67]+a[79]+a[78]+a[70]+a[73]+a[82]+a[77]+a[0]+a[48]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[26]+a[0])
|
|
36
|
+
if TH4874!=a9531:B.error(a[52]+a[72]+a[69]+a[0]+a[80]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[83]+a[0]+a[68]+a[79]+a[0]+a[78]+a[79]+a[84]+a[0]+a[77]+a[65]+a[84]+a[67]+a[72]+a[14]+a[0]+a[48]+a[76]+a[69]+a[65]+a[83]+a[69]+a[0]+a[84]+a[82]+a[89]+a[0]+a[65]+a[71]+a[65]+a[73]+a[78]+a[14]);sys.exit(1)
|
|
37
|
+
else:
|
|
38
|
+
a9531=A7801(a9531)
|
|
39
|
+
with open(a[14]+a[15]+a[14]+a[83]+a[69]+a[67]+a[82]+a[69]+a[84]+a[83]+a[15]+a[80]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[14]+a[75]+a[69]+a[89],a[87]+a[66])as RASD:RASD.write(JT3828.encrypt(a9531))
|
|
40
|
+
B.info(a[48]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[83]+a[0]+a[77]+a[65]+a[84]+a[67]+a[72]+a[69]+a[68]+a[0]+a[65]+a[78]+a[68]+a[0]+a[73]+a[84]+a[0]+a[87]+a[73]+a[76]+a[76]+a[0]+a[78]+a[79]+a[87]+a[0]+a[66]+a[69]+a[0]+a[89]+a[79]+a[85]+a[82]+a[0]+a[69]+a[78]+a[67]+a[82]+a[89]+a[80]+a[84]+a[73]+a[79]+a[78]+a[15]+a[68]+a[69]+a[67]+a[82]+a[89]+a[80]+a[84]+a[73]+a[79]+a[78]+a[0]+a[80]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[1])
|
|
41
|
+
return a9531
|
|
42
|
+
def FB1107SX(KB92):
|
|
43
|
+
G_HJ21=G9873();MB_11257=L54SD(G_HJ21)
|
|
44
|
+
if LMK849(a[14]+a[15]+D+a[15]+a[80]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[14]+a[75]+a[69]+a[89]):
|
|
45
|
+
with open(a[14]+a[15]+D+a[15]+a[80]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[14]+a[75]+a[69]+a[89],a[82]+a[66])as JG2351:GF0357=JG2351.read();AT487=MB_11257.decrypt(GF0357)
|
|
46
|
+
else:
|
|
47
|
+
AT487=AB53621(MB_11257)
|
|
48
|
+
if KB92==a[85]+a[80]+a[68]+a[65]+a[84]+a[69]:sys.exit()
|
|
49
|
+
return AT487
|
|
50
|
+
def JHG2152(GHLSDD):NBA45788=JL21(a[37]+a[78]+a[84]+a[69]+a[82]+a[0]+a[80]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[26]+a[0]);return NBA45788==N4512_3s2(GHLSDD)
|
|
51
|
+
def JH0847(CV3S412):
|
|
52
|
+
UY_45558=FB1107SX(a[69]+a[78]+a[67]+a[82]+a[89]+a[80]+a[84])
|
|
53
|
+
if JHG2152(UY_45558):
|
|
54
|
+
OPSD23=L54SD(G9873())
|
|
55
|
+
if LMK849(CV3S412)and CV3S412.endswith(F):
|
|
56
|
+
with open(CV3S412,a[82]+a[66])as JG398:GJ87e2=JG398.read()
|
|
57
|
+
BR51Ls=OPSD23.encrypt(GJ87e2)
|
|
58
|
+
with open(CV3S412,a[87]+a[66])as BJASD:BJASD.write(BR51Ls)
|
|
59
|
+
B.info(a[5]+a[83]+a[0]+a[72]+a[65]+a[83]+a[0]+a[66]+a[69]+a[69]+a[78]+a[0]+a[69]+a[78]+a[67]+a[82]+a[89]+a[80]+a[84]+a[69]+a[68]+a[0]+a[83]+a[85]+a[67]+a[67]+a[69]+a[83]+a[83]+a[70]+a[85]+a[76]+a[76]+a[89]+a[14],CV3S412)
|
|
60
|
+
else:B.error(CV3S412+a[0]+a[68]+a[79]+a[69]+a[83]+a[78]+a[7]+a[84]+a[0]+a[69]+a[88]+a[73]+a[83]+a[84]+a[12]+a[0]+a[79]+a[82]+a[0]+a[73]+a[83]+a[0]+a[65]+a[78]+a[0]+a[85]+a[78]+a[65]+a[67]+a[67]+a[69]+a[80]+a[84]+a[65]+a[66]+a[76]+a[69]+a[0]+a[70]+a[73]+a[76]+a[69]+a[0]+a[69]+a[88]+a[84]+a[69]+a[78]+a[83]+a[73]+a[79]+a[78]+a[1]);sys.exit(1)
|
|
61
|
+
else:B.error(a[48]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[83]+a[0]+a[68]+a[79]+a[78]+a[7]+a[84]+a[0]+a[77]+a[65]+a[84]+a[67]+a[72]+a[1]);sys.exit(1)
|
|
62
|
+
def IOA21H98(KAB46228):
|
|
63
|
+
PH6239=FB1107SX(a[68]+a[69]+a[67]+a[82]+a[89]+a[80]+a[84])
|
|
64
|
+
if JHG2152(PH6239):
|
|
65
|
+
UOPGG23441=L54SD(G9873())
|
|
66
|
+
if LMK849(KAB46228)and KAB46228.endswith(F):
|
|
67
|
+
with open(KAB46228,a[82]+a[66])as URT9934:JYT32446=URT9934.read()
|
|
68
|
+
try:UIAS9877=UOPGG23441.decrypt(JYT32446)
|
|
69
|
+
except EL714DO:B.error(KAB46228+a[0]+a[73]+a[83]+a[0]+a[78]+a[79]+a[84]+a[0]+a[69]+a[78]+a[67]+a[82]+a[89]+a[80]+a[84]+a[69]+a[68]+a[14]);sys.exit()
|
|
70
|
+
with open(KAB46228,a[87]+a[66])as BAB98455:BAB98455.write(UIAS9877)
|
|
71
|
+
B.info(KAB46228+a[0]+a[72]+a[65]+a[83]+a[0]+a[66]+a[69]+a[69]+a[78]+a[0]+a[68]+a[69]+a[67]+a[82]+a[89]+a[80]+a[84]+a[69]+a[68]+a[0]+a[83]+a[85]+a[67]+a[67]+a[69]+a[83]+a[83]+a[70]+a[85]+a[76]+a[76]+a[89]+a[14])
|
|
72
|
+
else:B.error(KAB46228+a[0]+a[68]+a[79]+a[69]+a[83]+a[78]+a[7]+a[84]+a[0]+a[69]+a[88]+a[73]+a[83]+a[84]+a[12]+a[0]+a[79]+a[82]+a[0]+a[73]+a[83]+a[0]+a[65]+a[78]+a[0]+a[85]+a[78]+a[65]+a[67]+a[67]+a[69]+a[80]+a[84]+a[65]+a[66]+a[76]+a[69]+a[0]+a[70]+a[73]+a[76]+a[69]+a[0]+a[69]+a[88]+a[84]+a[69]+a[78]+a[83]+a[73]+a[79]+a[78]+a[1]);sys.exit(1)
|
|
73
|
+
else:B.error(a[48]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[83]+a[0]+a[68]+a[79]+a[78]+a[7]+a[84]+a[0]+a[77]+a[65]+a[84]+a[67]+a[72]+a[1]);sys.exit(1)
|
|
74
|
+
def YO9322():
|
|
75
|
+
YR6248=FB1107SX(a[85]+a[80]+a[68]+a[65]+a[84]+a[69])
|
|
76
|
+
if JHG2152(YR6248):N_j214=G9873();BNS21=L54SD(N_j214);AB53621(BNS21)
|
|
77
|
+
else:B.error(a[48]+a[65]+a[83]+a[83]+a[75]+a[69]+a[89]+a[83]+a[0]+a[68]+a[79]+a[78]+a[7]+a[84]+a[0]+a[77]+a[65]+a[84]+a[67]+a[72]+a[1])
|
|
78
|
+
|
|
79
|
+
# fmt: on
|