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
|
File without changes
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Enables comparison of catalogs from the master catalog list and the user's RegScale instance"""
|
|
4
|
+
import json
|
|
5
|
+
import logging
|
|
6
|
+
import re
|
|
7
|
+
from urllib.parse import urlparse
|
|
8
|
+
|
|
9
|
+
import requests
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_new_catalog(url: str) -> dict:
|
|
15
|
+
"""
|
|
16
|
+
Function to download a catalog via API call
|
|
17
|
+
|
|
18
|
+
:param str url: URL to download the catalog from
|
|
19
|
+
:return: Catalog API response as a dictionary
|
|
20
|
+
:rtype: dict
|
|
21
|
+
"""
|
|
22
|
+
# make sure url is stripped
|
|
23
|
+
url = url.strip()
|
|
24
|
+
new_catalog = {}
|
|
25
|
+
try:
|
|
26
|
+
# call curl command to download the catalog
|
|
27
|
+
response = requests.get(url, timeout=60)
|
|
28
|
+
# parse into a dictionary
|
|
29
|
+
new_catalog = response.json()
|
|
30
|
+
except (requests.exceptions.MissingSchema, json.JSONDecodeError, requests.exceptions.RequestException) as ex:
|
|
31
|
+
logger.error("Error: %s on Catalog URL: %s", ex, url)
|
|
32
|
+
# return from the function
|
|
33
|
+
return new_catalog
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def is_valid_url(url: str) -> bool:
|
|
37
|
+
"""
|
|
38
|
+
Function to validate URL
|
|
39
|
+
|
|
40
|
+
:param str url: URL to validate
|
|
41
|
+
:return: Whether the URL is valid
|
|
42
|
+
:rtype: bool
|
|
43
|
+
"""
|
|
44
|
+
try:
|
|
45
|
+
result = urlparse(url)
|
|
46
|
+
return all([result.scheme, result.netloc])
|
|
47
|
+
except ValueError:
|
|
48
|
+
return False
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def dot_to_parentheses(input_string: str) -> str:
|
|
52
|
+
"""
|
|
53
|
+
Converts dot-separated issue identifiers to parentheses format.
|
|
54
|
+
|
|
55
|
+
:param str input_string: The string containing issue identifiers in dot-separated format.
|
|
56
|
+
:return: A string with issue identifiers converted to parentheses format.
|
|
57
|
+
:rtype: str
|
|
58
|
+
"""
|
|
59
|
+
return re.sub(r"([A-Z]+-\d+)\.(\d+)", r"\1(\2)", input_string.upper())
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def parentheses_to_dot(input_string: str) -> str:
|
|
63
|
+
"""
|
|
64
|
+
Converts parentheses-separated issue identifiers back to dot format.
|
|
65
|
+
|
|
66
|
+
:param str input_string: The string containing issue identifiers in parentheses format.
|
|
67
|
+
:return: A string with issue identifiers converted back to dot format.
|
|
68
|
+
:rtype: str
|
|
69
|
+
"""
|
|
70
|
+
return re.sub(r"([A-Z]+-\d+)\((\d+)\)", r"\1.\2", input_string.upper()).lower()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def objective_to_control_dot(input_string: str) -> str:
|
|
74
|
+
"""
|
|
75
|
+
Converts objective identifiers to control identifiers in dot format.
|
|
76
|
+
|
|
77
|
+
:param str input_string: The string containing objective identifiers.
|
|
78
|
+
:return: A string with objective identifiers converted to control identifiers in dot format.
|
|
79
|
+
:rtype: str
|
|
80
|
+
"""
|
|
81
|
+
# Convert the input string to lowercase
|
|
82
|
+
input_string = input_string.lower()
|
|
83
|
+
|
|
84
|
+
# Use regex to find the pattern and extract the desired part
|
|
85
|
+
match = re.match(r"([a-z]+-\d+(\.\d+)?)", input_string)
|
|
86
|
+
|
|
87
|
+
if match:
|
|
88
|
+
return match.group(1)
|
|
89
|
+
else:
|
|
90
|
+
logger.error(f"Failed to convert objective to control: {input_string}")
|
|
91
|
+
return input_string
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Enables comparison of catalogs from the master catalog list and the user's RegScale instance"""
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
# Standard Imports
|
|
7
|
+
import operator
|
|
8
|
+
|
|
9
|
+
import click # type: ignore
|
|
10
|
+
import requests # type: ignore
|
|
11
|
+
|
|
12
|
+
from regscale.core.app.api import Api
|
|
13
|
+
from regscale.core.app.logz import create_logger
|
|
14
|
+
from regscale.core.app.utils.app_utils import create_progress_object, error_and_exit
|
|
15
|
+
from regscale.core.app.utils.catalog_utils.common import get_new_catalog
|
|
16
|
+
from regscale.models.app_models.catalog_compare import CatalogCompare
|
|
17
|
+
|
|
18
|
+
# pylint: disable=line-too-long
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def display_menu() -> None:
|
|
22
|
+
"""
|
|
23
|
+
Start the process of comparing two catalogs, one from the master catalog list
|
|
24
|
+
and one from the user's RegScale instance
|
|
25
|
+
|
|
26
|
+
:rtype: None
|
|
27
|
+
"""
|
|
28
|
+
# set environment and application configuration
|
|
29
|
+
api = Api()
|
|
30
|
+
api.timeout = 180
|
|
31
|
+
|
|
32
|
+
# create logger function to log to the console
|
|
33
|
+
job_progress = create_progress_object()
|
|
34
|
+
logger = create_logger()
|
|
35
|
+
menu_counter: list = []
|
|
36
|
+
download_url: str = ""
|
|
37
|
+
new_catalog: dict = {}
|
|
38
|
+
# import master catalog list
|
|
39
|
+
data = CatalogCompare.get_master_catalogs(api=api)
|
|
40
|
+
# sort master catalogue list
|
|
41
|
+
catalogues = data["catalogs"]
|
|
42
|
+
catalogues.sort(key=operator.itemgetter("title"))
|
|
43
|
+
for i, catalog in enumerate(catalogues):
|
|
44
|
+
index = i + 1
|
|
45
|
+
# print each catalog in the master catalog list
|
|
46
|
+
print(f'{index}: {catalog["title"]}')
|
|
47
|
+
menu_counter.append(i)
|
|
48
|
+
# set status to False to run loop
|
|
49
|
+
status: bool = False
|
|
50
|
+
while not status:
|
|
51
|
+
# select catalog to run diagnostic
|
|
52
|
+
value = click.prompt(
|
|
53
|
+
"Please enter the number of the catalog you would like to run diagnostics on",
|
|
54
|
+
type=int,
|
|
55
|
+
)
|
|
56
|
+
# check if value exist that is selected
|
|
57
|
+
if value < min(menu_counter) or value > max(menu_counter):
|
|
58
|
+
print("That is not a valid selection, please try again")
|
|
59
|
+
else:
|
|
60
|
+
status = True
|
|
61
|
+
with job_progress:
|
|
62
|
+
# choose catalog to run diagnostics on
|
|
63
|
+
for i, catalog in enumerate(catalogues):
|
|
64
|
+
index = i + 1
|
|
65
|
+
short_title = catalog["defaultName"]
|
|
66
|
+
if index == value and catalog["downloadURL"]:
|
|
67
|
+
cat_uuid = catalog["uuid"]
|
|
68
|
+
download_url = catalog["downloadURL"]
|
|
69
|
+
break
|
|
70
|
+
|
|
71
|
+
# add task for retrieving new catalog
|
|
72
|
+
retrieving_new_catalog = job_progress.add_task(
|
|
73
|
+
f"[#f8b737]Retrieving selected catalog ({short_title}) from RegScale.com/resources.", total=1
|
|
74
|
+
)
|
|
75
|
+
# retrieve new catalog to run diagnostics on
|
|
76
|
+
new_catalog = get_new_catalog(url=download_url)
|
|
77
|
+
# update the task as complete
|
|
78
|
+
job_progress.update(retrieving_new_catalog, advance=1)
|
|
79
|
+
# add task for retrieving old catalog
|
|
80
|
+
retrieving_old_catalog = job_progress.add_task(
|
|
81
|
+
f"[#f8b737]Retrieving selected catalog ({short_title}) from RegScale application instance.",
|
|
82
|
+
total=1,
|
|
83
|
+
)
|
|
84
|
+
# retrieve old catalog to run diagnostics on
|
|
85
|
+
old_catalog = get_old_catalog(uuid_value=cat_uuid, api=api)
|
|
86
|
+
# update the task as complete
|
|
87
|
+
job_progress.update(retrieving_old_catalog, advance=1)
|
|
88
|
+
# add task to run diagnostics on new catalog
|
|
89
|
+
diagnosing_new_catalog = job_progress.add_task(
|
|
90
|
+
"[#21a5bb]Running diagnostics on catalog from RegScale.com/resources.",
|
|
91
|
+
total=1,
|
|
92
|
+
)
|
|
93
|
+
# run the diagnostics for the new selected catalog
|
|
94
|
+
new_results = CatalogCompare.run_new_diagnostics(new_diagnose_cat=new_catalog)
|
|
95
|
+
# update the task as complete
|
|
96
|
+
job_progress.update(diagnosing_new_catalog, advance=1)
|
|
97
|
+
# add task to run diagnostics on old catalog
|
|
98
|
+
diagnosing_old_catalog = job_progress.add_task(
|
|
99
|
+
"[#21a5bb]Running diagnosing on catalog from RegScale application instance.",
|
|
100
|
+
total=1,
|
|
101
|
+
)
|
|
102
|
+
# run the diagnostics for the old selected catalog
|
|
103
|
+
old_results = CatalogCompare.run_old_diagnostics(old_diagnose_cat=old_catalog)
|
|
104
|
+
# update the task as complete
|
|
105
|
+
job_progress.update(diagnosing_old_catalog, advance=1)
|
|
106
|
+
# add task to compare catalogs
|
|
107
|
+
comparing_catalogs = job_progress.add_task(
|
|
108
|
+
"[#ef5d23]Performing comparison on output of complete catalog diagnostics.",
|
|
109
|
+
total=1,
|
|
110
|
+
)
|
|
111
|
+
# compare catalog results
|
|
112
|
+
compare_dicts_shallow(dict_1=new_results.dict(), dict_2=old_results.dict(), logger=logger)
|
|
113
|
+
# update the task as complete
|
|
114
|
+
job_progress.update(comparing_catalogs, advance=1)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def get_old_catalog(uuid_value: str, api: Api) -> dict:
|
|
118
|
+
"""
|
|
119
|
+
Function to retrieve the old catalog from a RegScale instance via API & GraphQL
|
|
120
|
+
|
|
121
|
+
:param str uuid_value: UUID of the catalog to retrieve
|
|
122
|
+
:param Api api: API object
|
|
123
|
+
:return: dictionary of the old catalog
|
|
124
|
+
:rtype: dict
|
|
125
|
+
"""
|
|
126
|
+
old_catalog_data = {}
|
|
127
|
+
body = """
|
|
128
|
+
query {
|
|
129
|
+
catalogues(
|
|
130
|
+
skip: 0
|
|
131
|
+
take: 50
|
|
132
|
+
where: { uuid: { eq: "uuid_value" } }
|
|
133
|
+
) {
|
|
134
|
+
items {
|
|
135
|
+
title
|
|
136
|
+
uuid
|
|
137
|
+
keywords
|
|
138
|
+
securityControls {
|
|
139
|
+
id
|
|
140
|
+
objectives {
|
|
141
|
+
uuid
|
|
142
|
+
}
|
|
143
|
+
parameters {
|
|
144
|
+
uuid
|
|
145
|
+
}
|
|
146
|
+
cci {
|
|
147
|
+
uuid
|
|
148
|
+
}
|
|
149
|
+
tests {
|
|
150
|
+
uuid
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
pageInfo {
|
|
155
|
+
hasNextPage
|
|
156
|
+
}
|
|
157
|
+
totalCount
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
""".replace(
|
|
161
|
+
"uuid_value", uuid_value
|
|
162
|
+
)
|
|
163
|
+
try:
|
|
164
|
+
old_catalog_data = api.graph(query=body)["catalogues"]["items"][0]
|
|
165
|
+
except (IndexError, KeyError):
|
|
166
|
+
error_and_exit(f"Catalog with UUID: {uuid_value} not found in RegScale instance.")
|
|
167
|
+
return old_catalog_data
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def compare_dicts_shallow(dict_1: dict, dict_2: dict, logger: logging.Logger) -> None:
|
|
171
|
+
"""
|
|
172
|
+
Function to compare two dictionaries and output the results
|
|
173
|
+
|
|
174
|
+
:param dict dict_1: dictionary to compare
|
|
175
|
+
:param dict dict_2: dictionary to compare
|
|
176
|
+
:param logging.Logger logger: logger to use for console outputs
|
|
177
|
+
:rtype: None
|
|
178
|
+
"""
|
|
179
|
+
comparison = {
|
|
180
|
+
"title": "Catalog Titles",
|
|
181
|
+
"uuid": "Catalog UUIDs",
|
|
182
|
+
"keywords": "Catalog Keywords",
|
|
183
|
+
"cci_count": "CCI Counts",
|
|
184
|
+
"objective_count": "Objective Counts",
|
|
185
|
+
"parameter_count": "Parameter Counts",
|
|
186
|
+
"security_control_count": "Security Control Counts",
|
|
187
|
+
"test_count": "Test Counts",
|
|
188
|
+
}
|
|
189
|
+
for key, value in comparison.items():
|
|
190
|
+
if dict_1.get(key) != dict_2.get(key):
|
|
191
|
+
logger.info(f"{value} are not the same.")
|
|
192
|
+
else:
|
|
193
|
+
logger.info(f"{value} match.")
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Add functionality to diagnose catalog via API."""
|
|
4
|
+
|
|
5
|
+
# Standard Imports
|
|
6
|
+
import logging
|
|
7
|
+
import operator
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
import click # type: ignore
|
|
11
|
+
import requests # type: ignore
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from regscale.core.app.utils.app_utils import save_data_to
|
|
15
|
+
from regscale.core.app.utils.catalog_utils.common import get_new_catalog
|
|
16
|
+
from regscale.models.app_models.catalog_compare import CatalogCompare
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def display_menu() -> None:
|
|
20
|
+
"""
|
|
21
|
+
Display menu for catalog diagnostic and start the diagnostic process
|
|
22
|
+
|
|
23
|
+
:rtype: None
|
|
24
|
+
"""
|
|
25
|
+
# set environment and application configuration
|
|
26
|
+
from regscale.core.app.api import Api
|
|
27
|
+
|
|
28
|
+
api = Api()
|
|
29
|
+
api.timeout = 180
|
|
30
|
+
|
|
31
|
+
# create logger function to log to the console
|
|
32
|
+
logger = api.logger
|
|
33
|
+
menu_counter: list = []
|
|
34
|
+
download_url: str = ""
|
|
35
|
+
# import master catalog list
|
|
36
|
+
data = CatalogCompare.get_master_catalogs(api=api)
|
|
37
|
+
# sort master catalogue list
|
|
38
|
+
catalogues = data["catalogs"]
|
|
39
|
+
catalogues.sort(key=operator.itemgetter("title"))
|
|
40
|
+
for i, catalog in enumerate(catalogues):
|
|
41
|
+
index = i + 1
|
|
42
|
+
# print each catalog in the master catalog list
|
|
43
|
+
print(f'{index}: {catalog["title"]}')
|
|
44
|
+
menu_counter.append(index)
|
|
45
|
+
# set status to False to run loop
|
|
46
|
+
status: bool = False
|
|
47
|
+
value: Optional[int] = None
|
|
48
|
+
while not status:
|
|
49
|
+
# select catalog to run diagnostic
|
|
50
|
+
value = click.prompt(
|
|
51
|
+
"Please enter the number of the catalog you would like to run diagnostics on",
|
|
52
|
+
type=int,
|
|
53
|
+
)
|
|
54
|
+
# check if value exist that is selected
|
|
55
|
+
if value < min(menu_counter) or value > max(menu_counter):
|
|
56
|
+
print("That is not a valid selection, please try again")
|
|
57
|
+
else:
|
|
58
|
+
status = True
|
|
59
|
+
# choose catalog to run diagnostics on
|
|
60
|
+
for i, catalog in enumerate(catalogues):
|
|
61
|
+
index = i + 1
|
|
62
|
+
if index == value and catalog["downloadURL"]:
|
|
63
|
+
download_url = catalog["downloadURL"]
|
|
64
|
+
break
|
|
65
|
+
# retrieve new catalog to run diagnostics on
|
|
66
|
+
new_catalog = get_new_catalog(url=download_url)
|
|
67
|
+
# run the diagnostic output for the selected catalog
|
|
68
|
+
save_data_to(
|
|
69
|
+
file=Path("diagnostics.json"),
|
|
70
|
+
data=run_diagnostics(diagnose_cat=new_catalog, logger=logger).dict(),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def run_diagnostics(diagnose_cat: dict, logger: logging.Logger) -> CatalogCompare:
|
|
75
|
+
"""
|
|
76
|
+
Function to run diagnostics on a catalog
|
|
77
|
+
|
|
78
|
+
:param dict diagnose_cat: dictionary of a catalog to run diagnostics on
|
|
79
|
+
:param logging.Logger logger: Logger to log to the console
|
|
80
|
+
:return: CatalogCompare object
|
|
81
|
+
:rtype: CatalogCompare
|
|
82
|
+
"""
|
|
83
|
+
diagnostic_results = CatalogCompare().run_new_diagnostics(diagnose_cat)
|
|
84
|
+
|
|
85
|
+
# print information to the terminal
|
|
86
|
+
logger.info("The catalog you have selected for diagnostics is:")
|
|
87
|
+
logger.info(diagnostic_results.title)
|
|
88
|
+
logger.info("The uuid for this catalog is:")
|
|
89
|
+
logger.info(diagnostic_results.uuid)
|
|
90
|
+
logger.info("The list of contained keywords in this catalog is:")
|
|
91
|
+
logger.info(diagnostic_results.keywords)
|
|
92
|
+
logger.info(f"The number of CCIs in this catalog is: {diagnostic_results.cci_count}")
|
|
93
|
+
logger.info(f"The number of Objectives in this catalog is: {diagnostic_results.objective_count}")
|
|
94
|
+
logger.info(f"The number of Parameters in this catalog is: {diagnostic_results.parameter_count}")
|
|
95
|
+
logger.info(f"The number of Security Controls in this catalog is: {diagnostic_results.security_control_count}")
|
|
96
|
+
logger.info(f"The number of Tests in this catalog is: {diagnostic_results.test_count}")
|
|
97
|
+
return diagnostic_results
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Add functionality to download a catalog via API."""
|
|
4
|
+
import json.decoder
|
|
5
|
+
|
|
6
|
+
# Standard Imports
|
|
7
|
+
import operator
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Optional, Tuple
|
|
10
|
+
|
|
11
|
+
import click # type: ignore
|
|
12
|
+
import requests # type: ignore
|
|
13
|
+
|
|
14
|
+
from regscale.core.app.api import Api
|
|
15
|
+
from regscale.core.app.application import Application
|
|
16
|
+
from regscale.core.app.utils.app_utils import save_data_to
|
|
17
|
+
from regscale.core.app.utils.catalog_utils.common import get_new_catalog, is_valid_url
|
|
18
|
+
from regscale.models.app_models.catalog_compare import CatalogCompare
|
|
19
|
+
|
|
20
|
+
MENU_COUNTER: list = []
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def pull_catalogs() -> list[dict]:
|
|
24
|
+
"""
|
|
25
|
+
Function to pull the master catalogs from the API
|
|
26
|
+
|
|
27
|
+
:rtype: list[dict]
|
|
28
|
+
:return: The list of master catalogs
|
|
29
|
+
"""
|
|
30
|
+
api = Api()
|
|
31
|
+
data = CatalogCompare.get_master_catalogs(api=api)
|
|
32
|
+
# sort master catalog list
|
|
33
|
+
catalogues = data["catalogs"]
|
|
34
|
+
catalogues.sort(key=operator.itemgetter("title"))
|
|
35
|
+
return catalogues
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def display_menu(show_menu: bool) -> int:
|
|
39
|
+
"""
|
|
40
|
+
Function to display the menu for the catalog export and handle exporting the selected catalog
|
|
41
|
+
|
|
42
|
+
:param bool show_menu: Show the menu
|
|
43
|
+
:rtype: int
|
|
44
|
+
:return: The max index + 1 of the menu (one based for real world)
|
|
45
|
+
"""
|
|
46
|
+
api = Api()
|
|
47
|
+
catalogues = pull_catalogs()
|
|
48
|
+
# set environment and application configuration
|
|
49
|
+
api.timeout = 180
|
|
50
|
+
# import master catalog list
|
|
51
|
+
for i, catalog in enumerate(catalogues):
|
|
52
|
+
if show_menu:
|
|
53
|
+
print(f'{i + 1}: {catalog["title"]}')
|
|
54
|
+
MENU_COUNTER.append(i)
|
|
55
|
+
return max(MENU_COUNTER)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def select_catalog(catalog_index: int, logging: bool = True) -> Tuple[dict, dict]:
|
|
59
|
+
"""
|
|
60
|
+
Function to download the selected catalog
|
|
61
|
+
|
|
62
|
+
:param int catalog_index: Index of the selected catalog
|
|
63
|
+
:param bool logging: Enable logging
|
|
64
|
+
:rtype: Tuple[dict, dict]
|
|
65
|
+
:return: The new catalog as a dictionary and the registry dict of the selected catalog
|
|
66
|
+
"""
|
|
67
|
+
catalogues = pull_catalogs()
|
|
68
|
+
new_catalog = None
|
|
69
|
+
registry_item = None
|
|
70
|
+
app = Application()
|
|
71
|
+
logger = app.logger
|
|
72
|
+
status: bool = False
|
|
73
|
+
value: Optional[int] = None
|
|
74
|
+
download_url: str = ""
|
|
75
|
+
catalog_name: str = ""
|
|
76
|
+
while not status:
|
|
77
|
+
if catalog_index == 0:
|
|
78
|
+
value = click.prompt(
|
|
79
|
+
"Please enter the number of the catalog you would like to download",
|
|
80
|
+
type=int,
|
|
81
|
+
)
|
|
82
|
+
else:
|
|
83
|
+
value = catalog_index
|
|
84
|
+
if MENU_COUNTER and value < min(MENU_COUNTER) or MENU_COUNTER and value > max(MENU_COUNTER):
|
|
85
|
+
print("That is not a valid selection, please try again")
|
|
86
|
+
else:
|
|
87
|
+
status = True
|
|
88
|
+
# Choose catalog to export
|
|
89
|
+
for i, catalog in enumerate(catalogues):
|
|
90
|
+
if i + 1 == value and catalog["url"]:
|
|
91
|
+
registry_item = catalog
|
|
92
|
+
download_url = catalog["downloadURL"].strip()
|
|
93
|
+
logger.debug("ix+1: %i, URL: %s", i + 1, download_url)
|
|
94
|
+
catalog_name = catalog["defaultName"].replace(" ", "_")
|
|
95
|
+
break
|
|
96
|
+
if is_valid_url(download_url):
|
|
97
|
+
new_catalog = get_new_catalog(url=download_url)
|
|
98
|
+
save_data_to(
|
|
99
|
+
file=Path(f"{catalog_name}.json"),
|
|
100
|
+
data=new_catalog,
|
|
101
|
+
output_log=logging,
|
|
102
|
+
)
|
|
103
|
+
return new_catalog, registry_item
|