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,473 @@
|
|
|
1
|
+
"""Allow an API Wrapper for the CLI"""
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
import base64
|
|
5
|
+
import os
|
|
6
|
+
from os import getenv
|
|
7
|
+
from typing import Union
|
|
8
|
+
from wsgiref import simple_server
|
|
9
|
+
|
|
10
|
+
from click import Command, Group
|
|
11
|
+
from flask import (
|
|
12
|
+
Flask,
|
|
13
|
+
Response,
|
|
14
|
+
redirect,
|
|
15
|
+
render_template,
|
|
16
|
+
render_template_string,
|
|
17
|
+
request,
|
|
18
|
+
url_for,
|
|
19
|
+
)
|
|
20
|
+
from flask_rebar import Rebar
|
|
21
|
+
from flask_restx import Api
|
|
22
|
+
from importlib_resources import files
|
|
23
|
+
from rich.console import Console
|
|
24
|
+
from werkzeug.utils import secure_filename
|
|
25
|
+
|
|
26
|
+
from regscale import __version__
|
|
27
|
+
from regscale.core.app.internal.login import login
|
|
28
|
+
from regscale.core.app.logz import create_logger
|
|
29
|
+
from regscale.core.app.utils.app_utils import walk_directory_for_files
|
|
30
|
+
from regscale.core.app.utils.regscale_utils import update_regscale_config
|
|
31
|
+
from regscale.core.server.helpers import (
|
|
32
|
+
create_view_func,
|
|
33
|
+
delete_all_items_in_directory,
|
|
34
|
+
generate_parameters_model,
|
|
35
|
+
get_site_info,
|
|
36
|
+
get_catgalogues,
|
|
37
|
+
get_profiles,
|
|
38
|
+
get_ssp_name,
|
|
39
|
+
get_ssps,
|
|
40
|
+
generate,
|
|
41
|
+
)
|
|
42
|
+
from regscale.regscale import cli
|
|
43
|
+
|
|
44
|
+
# pylint: disable=line-too-long, logging-fstring-interpolation, invalid-name
|
|
45
|
+
|
|
46
|
+
current_file_size = 0
|
|
47
|
+
|
|
48
|
+
app = Flask(__name__)
|
|
49
|
+
|
|
50
|
+
logger = create_logger()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@app.route("/")
|
|
54
|
+
def index():
|
|
55
|
+
"""Index route"""
|
|
56
|
+
return redirect(url_for("home"))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# setup swagger
|
|
60
|
+
api = Api(
|
|
61
|
+
app,
|
|
62
|
+
version=__version__,
|
|
63
|
+
title="RegScale-CLI REST API Wrapper",
|
|
64
|
+
description="A REST API wrapper support GET and POST requests for the RegScale-CLI.",
|
|
65
|
+
doc="/swagger/",
|
|
66
|
+
default="RegScale-CLI REST API",
|
|
67
|
+
default_label="RegScale-CLI REST API Operations",
|
|
68
|
+
template_folder=files("regscale.core.server.templates"),
|
|
69
|
+
debug=True,
|
|
70
|
+
)
|
|
71
|
+
# setup redoc
|
|
72
|
+
rebar = Rebar()
|
|
73
|
+
registry = rebar.create_handler_registry()
|
|
74
|
+
|
|
75
|
+
if not os.path.exists("artifacts"):
|
|
76
|
+
os.makedirs("artifacts")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# recursive function to generate routes from a click group
|
|
80
|
+
def generate_routes(api_instance: Api, group: Union[Group, Command], path: str = ""):
|
|
81
|
+
"""Generate routes for the app, recursively
|
|
82
|
+
since group is assumed to be a click.Group, we get the command_name and command for all of those items.
|
|
83
|
+
an endpoint_path is created. if the command is found to be a click.Group it is called on itself until we have a
|
|
84
|
+
click command.
|
|
85
|
+
|
|
86
|
+
:param Api api_instance: the flask_restx.Api instance
|
|
87
|
+
:param Union[Group, Command] group: A Group or Command from click
|
|
88
|
+
:param str path: str a representation of the endpoint path, defaults to ""
|
|
89
|
+
"""
|
|
90
|
+
for command_name, command in group.commands.items():
|
|
91
|
+
endpoint_path = f"{path}/{command_name}"
|
|
92
|
+
if command.name in {
|
|
93
|
+
"encrypt",
|
|
94
|
+
"decrypt",
|
|
95
|
+
"change_passkey",
|
|
96
|
+
"catalog",
|
|
97
|
+
"assessments",
|
|
98
|
+
"control_editor",
|
|
99
|
+
}:
|
|
100
|
+
continue
|
|
101
|
+
if isinstance(command, Group) and command.name in {"issues"}:
|
|
102
|
+
continue
|
|
103
|
+
if isinstance(command, Group):
|
|
104
|
+
# Generate routes for nested group
|
|
105
|
+
generate_routes(api_instance, command, endpoint_path)
|
|
106
|
+
else:
|
|
107
|
+
# generate the CommandResource class
|
|
108
|
+
resource_class = create_view_func(command)
|
|
109
|
+
# if command has params, generate the parameters model for that command
|
|
110
|
+
if command.params:
|
|
111
|
+
# generate the parameters model
|
|
112
|
+
parameters_model = generate_parameters_model(api_instance, command)
|
|
113
|
+
resource_class.post = api.expect(parameters_model)(resource_class.post)
|
|
114
|
+
api.add_resource(resource_class, endpoint_path)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
# generate all the routes dynamically from the click information
|
|
118
|
+
generate_routes(api, cli)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@app.route("/redoc/")
|
|
122
|
+
def redoc():
|
|
123
|
+
"""return render template string"""
|
|
124
|
+
return render_template_string(
|
|
125
|
+
"""
|
|
126
|
+
<!DOCTYPE html>
|
|
127
|
+
<html>
|
|
128
|
+
<head>
|
|
129
|
+
<title>ReDoc</title>
|
|
130
|
+
<meta charset="utf-8"/>
|
|
131
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
132
|
+
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
|
133
|
+
<style>
|
|
134
|
+
body, html { margin: 0; padding: 0; }
|
|
135
|
+
#redoc { width: 100vw; height: 100vw; position: sticky; }
|
|
136
|
+
</style>
|
|
137
|
+
</head>
|
|
138
|
+
<body>
|
|
139
|
+
<div id="redoc"></div>
|
|
140
|
+
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
|
|
141
|
+
<script>
|
|
142
|
+
Redoc.init('/swagger.json', {}, document.getElementById('redoc'))
|
|
143
|
+
</script>
|
|
144
|
+
</body>
|
|
145
|
+
</html>
|
|
146
|
+
"""
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@app.route("/home")
|
|
151
|
+
def home():
|
|
152
|
+
"""Index route"""
|
|
153
|
+
return render_template("index.html", site_info=get_site_info())
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@app.route("/auth", methods=["GET"])
|
|
157
|
+
def auth():
|
|
158
|
+
"""Auth route"""
|
|
159
|
+
return render_template("login.html", site_info=get_site_info())
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@app.route("/login-token", methods=["POST"])
|
|
163
|
+
def login_token():
|
|
164
|
+
domain = request.form["domain"].split(" ")[0] # split on space to avoid injection
|
|
165
|
+
token = request.form["token"]
|
|
166
|
+
if "Bearer" not in token:
|
|
167
|
+
token = f"Bearer {token}"
|
|
168
|
+
if len(token.split(" ")) != 2: # if the length is not 2, then it is not a valid token
|
|
169
|
+
raise ValueError(f"Invalid token: {token}")
|
|
170
|
+
if ";" in token or "&&" in token or "|" in token:
|
|
171
|
+
raise ValueError(f"Invalid token: {token}")
|
|
172
|
+
if not domain.endswith("/"):
|
|
173
|
+
domain += "/"
|
|
174
|
+
# set the domain in init.yaml
|
|
175
|
+
config_response = update_regscale_config(str_param="domain", val=domain)
|
|
176
|
+
if config_response != "Config updated":
|
|
177
|
+
raise ValueError(f"Could not update domain in init.yaml: {config_response}")
|
|
178
|
+
# login to the RegScale instance
|
|
179
|
+
auth_token = login(token=token)
|
|
180
|
+
logger.debug(f"Authenticated with {auth_token}")
|
|
181
|
+
return redirect(url_for("home"))
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@app.route("/upload_ssp", methods=["GET"])
|
|
185
|
+
def upload_ssp():
|
|
186
|
+
"""Upload a file for processing"""
|
|
187
|
+
regscale_profiles = get_profiles()
|
|
188
|
+
# Get list of catalogs
|
|
189
|
+
regscale_catalogues = get_catgalogues()
|
|
190
|
+
return render_template(
|
|
191
|
+
"upload_ssp.html",
|
|
192
|
+
regscale_catalogues=regscale_catalogues,
|
|
193
|
+
regscale_profiles=regscale_profiles,
|
|
194
|
+
site_info=get_site_info(),
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
@app.route("/process_file", methods=["POST"])
|
|
199
|
+
def process_file():
|
|
200
|
+
"""process uploaded file"""
|
|
201
|
+
logger.debug(f"Request: {request.form}")
|
|
202
|
+
file = request.files["file"]
|
|
203
|
+
version = request.form["fedrampVersion"]
|
|
204
|
+
logger.info(f"Parsed version: {version}")
|
|
205
|
+
catalogue_id = request.form["regscale_catalogue_id"]
|
|
206
|
+
profile_id = request.form["regscale_profile_id"]
|
|
207
|
+
load_missing_controls_str = request.form.get("load_missing_controls")
|
|
208
|
+
load_missing_controls_bool = ast.literal_eval(load_missing_controls_str)
|
|
209
|
+
filename = secure_filename(file.filename)
|
|
210
|
+
default_csv_path = "./artifacts/import-results.csv"
|
|
211
|
+
if os.path.exists(default_csv_path):
|
|
212
|
+
os.remove(default_csv_path)
|
|
213
|
+
artifacts_dir = "artifacts"
|
|
214
|
+
file_path = os.path.join(artifacts_dir, filename)
|
|
215
|
+
create_logger()
|
|
216
|
+
# Check if the file already exists and warn if needed
|
|
217
|
+
if os.path.exists(file_path):
|
|
218
|
+
# Logic to display a warning and handle overwrite (e.g., via user confirmation)
|
|
219
|
+
pass
|
|
220
|
+
|
|
221
|
+
# Save the file to the 'artifacts' directory
|
|
222
|
+
file.save(file_path)
|
|
223
|
+
if version.lower() == "rev4":
|
|
224
|
+
from regscale.integrations.public.fedramp.fedramp_docx import process_fedramp_docx_by_profile_id
|
|
225
|
+
|
|
226
|
+
(
|
|
227
|
+
csv_path,
|
|
228
|
+
result_output,
|
|
229
|
+
implementation_results,
|
|
230
|
+
) = process_fedramp_docx_by_profile_id(
|
|
231
|
+
file_path=file_path,
|
|
232
|
+
profile_id=int(profile_id),
|
|
233
|
+
load_missing=load_missing_controls_bool,
|
|
234
|
+
)
|
|
235
|
+
return Response(generate(app, file_path, filename, catalogue_id), content_type="text/html")
|
|
236
|
+
elif version.lower() == "rev5docx":
|
|
237
|
+
from regscale.integrations.public.fedramp.fedramp_five import process_fedramp_docx_v5
|
|
238
|
+
|
|
239
|
+
# parse rev 5
|
|
240
|
+
appendix_file = request.files["fileAppendix"]
|
|
241
|
+
appendix_file_name = secure_filename(appendix_file.filename)
|
|
242
|
+
appendix_file_path = os.path.join(artifacts_dir, appendix_file_name)
|
|
243
|
+
appendix_file.save(appendix_file_path)
|
|
244
|
+
ssp_id = process_fedramp_docx_v5(
|
|
245
|
+
file_name=file_path,
|
|
246
|
+
base_fedramp_profile_id=int(profile_id),
|
|
247
|
+
save_data=False,
|
|
248
|
+
add_missing=load_missing_controls_bool,
|
|
249
|
+
appendix_a_file_name=appendix_file_path,
|
|
250
|
+
)
|
|
251
|
+
from urllib.parse import urljoin
|
|
252
|
+
|
|
253
|
+
ssp_url = urljoin(get_site_info()["domain"], f"form/securityplans/{ssp_id}")
|
|
254
|
+
return redirect(ssp_url)
|
|
255
|
+
else:
|
|
256
|
+
return Response(generate(app, file_path, filename, catalogue_id), content_type="text/html")
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
@app.route("/final_results")
|
|
260
|
+
def final_results():
|
|
261
|
+
"""
|
|
262
|
+
Render the final results page with the grouped CSV data and result output
|
|
263
|
+
"""
|
|
264
|
+
csv_path = request.args.get("csv_path", "")
|
|
265
|
+
result_output = request.args.get("result_output", "")
|
|
266
|
+
filename = request.args.get("filename", "")
|
|
267
|
+
return load_results(csv_path, result_output, filename)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def load_results(csv_path, result_output_str, filename):
|
|
271
|
+
"""
|
|
272
|
+
Load the results from the SSP processing and render the final results page
|
|
273
|
+
"""
|
|
274
|
+
import pandas as pd # Optimize import performance
|
|
275
|
+
|
|
276
|
+
# convert result_output to diction
|
|
277
|
+
result_output = ast.literal_eval(result_output_str)
|
|
278
|
+
|
|
279
|
+
# Read and group the CSV data by error level (do this now as it is expensive)
|
|
280
|
+
csv_data = pd.read_csv(csv_path)
|
|
281
|
+
# if the csv file is not empty
|
|
282
|
+
if not csv_data.empty:
|
|
283
|
+
# group the csv data
|
|
284
|
+
csv_data_grouped = (
|
|
285
|
+
# sort the csv data by the model_layer and timestamp columns
|
|
286
|
+
csv_data.sort_values(["model_layer", "timestamp"])
|
|
287
|
+
# group the csv data by the level column
|
|
288
|
+
.groupby("level")
|
|
289
|
+
# convert dataframe to a dictionary and orient by the records
|
|
290
|
+
.apply(lambda x: x.to_dict(orient="records"))
|
|
291
|
+
# convert to a dictionary
|
|
292
|
+
.to_dict()
|
|
293
|
+
)
|
|
294
|
+
value_counts = (
|
|
295
|
+
# group the csv data by the level column
|
|
296
|
+
csv_data.drop("timestamp", axis="columns")
|
|
297
|
+
.drop("model_layer", axis="columns")
|
|
298
|
+
.drop("record_type", axis="columns")
|
|
299
|
+
.drop("event", axis="columns")
|
|
300
|
+
.groupby("level")
|
|
301
|
+
.agg(["count"])
|
|
302
|
+
.to_dict()
|
|
303
|
+
)
|
|
304
|
+
value_counts["Results"] = value_counts.pop(("Unnamed: 0", "count"))
|
|
305
|
+
category_counts = csv_data["record_type"].value_counts().to_dict()
|
|
306
|
+
results = value_counts["Results"]
|
|
307
|
+
# ensure that these exist as numbers
|
|
308
|
+
if "Error" not in results:
|
|
309
|
+
results["Error"] = 0
|
|
310
|
+
if "Info" not in results:
|
|
311
|
+
results["Info"] = 0
|
|
312
|
+
else:
|
|
313
|
+
logger.warning(f"{csv_path} is empty.")
|
|
314
|
+
csv_data_grouped = {}
|
|
315
|
+
results = {}
|
|
316
|
+
category_counts = {}
|
|
317
|
+
# Render the success page with the grouped CSV data and result output
|
|
318
|
+
return render_template(
|
|
319
|
+
"upload_ssp_result.html",
|
|
320
|
+
site_info=get_site_info(),
|
|
321
|
+
csv_data_grouped=csv_data_grouped,
|
|
322
|
+
results=results,
|
|
323
|
+
result_output=result_output,
|
|
324
|
+
category_counts=category_counts,
|
|
325
|
+
filename=filename,
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
@app.route("/make_base64", methods=["GET"])
|
|
330
|
+
def make_base64():
|
|
331
|
+
"""Form to upload a file to convert to base64 string"""
|
|
332
|
+
return render_template("make_base64.html", site_info=get_site_info())
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
@app.route("/encode_base", methods=["POST"])
|
|
336
|
+
def encode_base64():
|
|
337
|
+
"""Return Base64-encoded string as file"""
|
|
338
|
+
if request.method == "POST":
|
|
339
|
+
# Check if the POST request has the file part
|
|
340
|
+
if "file" not in request.files:
|
|
341
|
+
return "No file part"
|
|
342
|
+
file = request.files["file"]
|
|
343
|
+
# If the user does not select a file, the browser submits an empty file without a filename.
|
|
344
|
+
if file.filename == "":
|
|
345
|
+
return "No selected file"
|
|
346
|
+
|
|
347
|
+
if file:
|
|
348
|
+
# Convert the uploaded file to Base64
|
|
349
|
+
file_content = file.read()
|
|
350
|
+
base64_content = base64.b64encode(file_content).decode("utf-8")
|
|
351
|
+
|
|
352
|
+
# Create a filename for downloading
|
|
353
|
+
download_filename = f"{file.filename}.txt"
|
|
354
|
+
|
|
355
|
+
# Set up the response object for downloading
|
|
356
|
+
response = Response(base64_content, content_type="text/plain")
|
|
357
|
+
response.headers["Content-Disposition"] = f"attachment; filename={download_filename}"
|
|
358
|
+
|
|
359
|
+
return response
|
|
360
|
+
else:
|
|
361
|
+
return render_template("make_base64.html", site_info=get_site_info())
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
@app.route("/upload_STIG", methods=["GET"])
|
|
365
|
+
def create_stig_upload_form() -> str:
|
|
366
|
+
"""
|
|
367
|
+
Create a form for uploading STIG files to RegScale
|
|
368
|
+
|
|
369
|
+
:return: The rendered HTML form
|
|
370
|
+
:rtype: str
|
|
371
|
+
"""
|
|
372
|
+
"""Upload a file for processing"""
|
|
373
|
+
# Get list of SSPs from the RegScale instance
|
|
374
|
+
regscale_ssps = get_ssps()
|
|
375
|
+
regscale_catalogues = get_catgalogues()
|
|
376
|
+
return render_template(
|
|
377
|
+
"upload_STIG.html",
|
|
378
|
+
regscale_ssps=regscale_ssps,
|
|
379
|
+
regscale_catalogues=regscale_catalogues,
|
|
380
|
+
site_info=get_site_info(),
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
@app.route("/process_stig_file", methods=["POST"])
|
|
385
|
+
async def process_stig_file():
|
|
386
|
+
"""process stig file(s) for uploading to RegScale"""
|
|
387
|
+
import time
|
|
388
|
+
|
|
389
|
+
file_directory = "stig_artifacts"
|
|
390
|
+
start_time = time.time()
|
|
391
|
+
ssp_id = request.form["regscale_ssp_id"]
|
|
392
|
+
ckl_file = request.files.get("cklFile")
|
|
393
|
+
zip_file = request.files.get("zip")
|
|
394
|
+
start_msg, warning_msg, result_msg = "", "", ""
|
|
395
|
+
# See if stig artifacts exists, if not create it, else remove all the contents
|
|
396
|
+
if not os.path.exists(file_directory):
|
|
397
|
+
os.mkdir(file_directory)
|
|
398
|
+
else:
|
|
399
|
+
delete_all_items_in_directory(file_directory)
|
|
400
|
+
if ckl_file:
|
|
401
|
+
file_count = 1
|
|
402
|
+
start_msg = f"Processing {ckl_file.filename} STIG file for SSP #{ssp_id}..."
|
|
403
|
+
ckl_file.save(f"{file_directory}{os.sep}{secure_filename(ckl_file.filename)}")
|
|
404
|
+
elif zip_file:
|
|
405
|
+
import zipfile
|
|
406
|
+
|
|
407
|
+
zip_path = f"{file_directory}{os.sep}{secure_filename(zip_file.filename)}"
|
|
408
|
+
zip_file.save(zip_path)
|
|
409
|
+
with zipfile.ZipFile(zip_path, "r") as zip_ref:
|
|
410
|
+
# Extract all the files to a specific directory
|
|
411
|
+
zip_ref.extractall(file_directory)
|
|
412
|
+
# delete the zip file after extracting
|
|
413
|
+
os.remove(zip_path)
|
|
414
|
+
ckl_files, upload_count = walk_directory_for_files(file_directory)
|
|
415
|
+
# delete all the files in the directory except .ckl files
|
|
416
|
+
delete_all_items_in_directory(file_directory, keep_ext=".ckl")
|
|
417
|
+
file_count = len(ckl_files)
|
|
418
|
+
if non_ckl_count := upload_count - file_count:
|
|
419
|
+
warning_msg = (
|
|
420
|
+
f"{non_ckl_count}/{upload_count} " "file(s) will not processed because they are not .ckl files."
|
|
421
|
+
)
|
|
422
|
+
if non_ckl_count == upload_count:
|
|
423
|
+
logger.error("No file(s) were selected for processing because none of them are .ckl files.")
|
|
424
|
+
return redirect(url_for("create_stig_upload_form"))
|
|
425
|
+
start_msg = f"Processing {file_count} STIG file(s) for SSP #{ssp_id}..."
|
|
426
|
+
else:
|
|
427
|
+
logger.error("No file(s) were selected for processing.")
|
|
428
|
+
return redirect(url_for("create_stig_upload_form"))
|
|
429
|
+
# Process the STIG file(s) and upload to RegScale
|
|
430
|
+
from regscale.integrations.commercial.stigv2.stig_integration import StigIntegration
|
|
431
|
+
|
|
432
|
+
StigIntegration.sync_assets(plan_id=int(ssp_id), path="stig_artifacts")
|
|
433
|
+
|
|
434
|
+
StigIntegration.sync_findings(plan_id=int(ssp_id), path="stig_artifacts")
|
|
435
|
+
|
|
436
|
+
time_elapsed = f"{round(time.time() - start_time, 2)} seconds."
|
|
437
|
+
result_msg = f"Processed {file_count} STIG file(s) for SSP #{ssp_id} in {time_elapsed}"
|
|
438
|
+
return render_template(
|
|
439
|
+
"upload_STIG_result.html",
|
|
440
|
+
results={
|
|
441
|
+
"file_count": file_count,
|
|
442
|
+
"start_msg": start_msg,
|
|
443
|
+
"warning_msg": warning_msg,
|
|
444
|
+
"result_msg": result_msg,
|
|
445
|
+
"ssp_id": ssp_id,
|
|
446
|
+
"ssp_name": get_ssp_name(ssp_id),
|
|
447
|
+
"time_elapsed": time_elapsed,
|
|
448
|
+
},
|
|
449
|
+
site_info=get_site_info(),
|
|
450
|
+
)
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
def run_app(
|
|
454
|
+
port: int = int(getenv("REGSCALE_FLASK_PORT", "5555")),
|
|
455
|
+
debug: bool = getenv("DEBUG_FLASK_APP", "False") == "True",
|
|
456
|
+
):
|
|
457
|
+
"""Run the CLI as a flask app
|
|
458
|
+
|
|
459
|
+
:param int port: The port to serve flask on
|
|
460
|
+
:param bool debug: Whether to run the flask application in debug mode
|
|
461
|
+
"""
|
|
462
|
+
Console().print(f"Running on http://127.0.0.1:{port}/")
|
|
463
|
+
Console().print(f"Swagger docs at http://127.0.0.1:{port}/swagger/")
|
|
464
|
+
Console().print("Press CTRL+C to quit")
|
|
465
|
+
try:
|
|
466
|
+
if debug:
|
|
467
|
+
logger.info("Running in debug mode.")
|
|
468
|
+
app.run(debug=True, port=port)
|
|
469
|
+
else:
|
|
470
|
+
server = simple_server.make_server("0.0.0.0", port, app)
|
|
471
|
+
server.serve_forever()
|
|
472
|
+
except KeyboardInterrupt:
|
|
473
|
+
Console().print("Exiting")
|