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,260 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""RegScale SonarCloud Integration"""
|
|
4
|
+
|
|
5
|
+
# standard python imports
|
|
6
|
+
import math
|
|
7
|
+
import sys
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
import click
|
|
11
|
+
import requests # type: ignore
|
|
12
|
+
|
|
13
|
+
from regscale.core.app.api import Api
|
|
14
|
+
from regscale.core.app.application import Application
|
|
15
|
+
from regscale.core.app.logz import create_logger
|
|
16
|
+
from regscale.core.app.utils.app_utils import (
|
|
17
|
+
get_current_datetime,
|
|
18
|
+
days_between,
|
|
19
|
+
)
|
|
20
|
+
from regscale.models import regscale_id, regscale_module
|
|
21
|
+
from regscale.models.regscale_models.assessment import Assessment
|
|
22
|
+
from regscale.models.regscale_models.issue import Issue
|
|
23
|
+
|
|
24
|
+
# create logger function to log to the console
|
|
25
|
+
logger = create_logger()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_sonarcloud_results(config: dict) -> list[list[dict]]:
|
|
29
|
+
"""
|
|
30
|
+
Retrieve Sonarcloud Results from the Sonarcloud.io API
|
|
31
|
+
:param dict config: RegScale CLI configuration
|
|
32
|
+
:return: json response data from API GET request
|
|
33
|
+
:rtype: list[list[dict]]
|
|
34
|
+
"""
|
|
35
|
+
# api endpoint
|
|
36
|
+
url = "https://sonarcloud.io/api/issues/search"
|
|
37
|
+
# SONAR_TOKEN from Sonarcloud
|
|
38
|
+
token = config["sonarToken"]
|
|
39
|
+
# arguments to pass to the API call
|
|
40
|
+
query = {
|
|
41
|
+
"organization": "regscale",
|
|
42
|
+
"projects": "RegScale_regscale",
|
|
43
|
+
"branch": "main",
|
|
44
|
+
"projectKey": "RegScale_regscale",
|
|
45
|
+
"statuses": "OPEN, CONFIRMED, REOPENED",
|
|
46
|
+
"createdInLast": "1m",
|
|
47
|
+
"ps": 500,
|
|
48
|
+
}
|
|
49
|
+
# GET request pulls in data to check results size
|
|
50
|
+
r = requests.get(url, auth=(str(token), ""), params=query)
|
|
51
|
+
# if the status code does not equal 200
|
|
52
|
+
if r and not r.ok:
|
|
53
|
+
# exit the script gracefully
|
|
54
|
+
sys.exit("Sonarcloud API call failed please check the configuration")
|
|
55
|
+
# pull in response data to a dictionary
|
|
56
|
+
data = r.json()
|
|
57
|
+
# find the total results number
|
|
58
|
+
total = data["paging"]["total"]
|
|
59
|
+
# find the number of results in each result page
|
|
60
|
+
size = data["paging"]["pageSize"]
|
|
61
|
+
# calculate the number of pages to iterate through sequentially
|
|
62
|
+
pages = math.ceil(total / size)
|
|
63
|
+
# create an empty list to hold multiple pages of data
|
|
64
|
+
complete = []
|
|
65
|
+
# loop through each page number
|
|
66
|
+
for i in range(1, pages + 1, 1):
|
|
67
|
+
# parameters to pass to the API call
|
|
68
|
+
filters = {
|
|
69
|
+
"organization": "regscale",
|
|
70
|
+
"projects": "RegScale_regscale",
|
|
71
|
+
"branch": "main",
|
|
72
|
+
"projectKey": "RegScale_regscale",
|
|
73
|
+
"statuses": "OPEN, CONFIRMED, REOPENED",
|
|
74
|
+
"createdInLast": "1m",
|
|
75
|
+
"ps": 500,
|
|
76
|
+
"p": f"{i}",
|
|
77
|
+
}
|
|
78
|
+
# for each page make a GET request to pull in the data
|
|
79
|
+
r = requests.get(url, auth=(str(token), ""), params=filters)
|
|
80
|
+
# pull in response data to a dictionary
|
|
81
|
+
data = r.json()
|
|
82
|
+
# extract only the issues from the data
|
|
83
|
+
issues = data["issues"]
|
|
84
|
+
# add each page to the total results page
|
|
85
|
+
complete.append(issues)
|
|
86
|
+
# return the list of json response objects for use
|
|
87
|
+
return complete
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def build_data(api: Api) -> list[dict]:
|
|
91
|
+
"""
|
|
92
|
+
Build vulnerability alert data list
|
|
93
|
+
:param Api api: API object
|
|
94
|
+
:return: vulnerability data list
|
|
95
|
+
:rtype: list[dict]
|
|
96
|
+
"""
|
|
97
|
+
# execute GET request
|
|
98
|
+
data = get_sonarcloud_results(config=api.config)
|
|
99
|
+
# create empty list to hold json response dicts
|
|
100
|
+
vulnerability_data_list = []
|
|
101
|
+
# loop through the lists in API response data
|
|
102
|
+
for result in data:
|
|
103
|
+
# loop through the list of dicts in the API response data
|
|
104
|
+
for i, issue in enumerate(result):
|
|
105
|
+
# format datetime stamp to use with days_between function
|
|
106
|
+
create_date = issue["creationDate"][0:19] + "Z"
|
|
107
|
+
# build vulnerability list
|
|
108
|
+
vulnerability_data_list.append(
|
|
109
|
+
{
|
|
110
|
+
"key": issue["key"],
|
|
111
|
+
"severity": issue["severity"],
|
|
112
|
+
"component": issue["component"],
|
|
113
|
+
"status": issue["status"],
|
|
114
|
+
"message": issue["message"],
|
|
115
|
+
"creationDate": issue["creationDate"][0:19],
|
|
116
|
+
"updateDate": issue["updateDate"][0:19],
|
|
117
|
+
"type": issue["type"],
|
|
118
|
+
"days_elapsed": days_between(vuln_time=create_date),
|
|
119
|
+
}
|
|
120
|
+
)
|
|
121
|
+
return vulnerability_data_list
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def build_dataframes(api: Api) -> str:
|
|
125
|
+
"""
|
|
126
|
+
Build pandas dataframes from vulnerability alert data list
|
|
127
|
+
|
|
128
|
+
:param Api api: API object
|
|
129
|
+
:return: dataframe as an HTML table
|
|
130
|
+
:rtype: str
|
|
131
|
+
"""
|
|
132
|
+
import pandas as pd # Optimize import performance
|
|
133
|
+
|
|
134
|
+
# create vulnerability data list
|
|
135
|
+
vuln_data_list = build_data(api=api)
|
|
136
|
+
|
|
137
|
+
# for vulnerability in vuln_data_list:
|
|
138
|
+
df = pd.DataFrame(vuln_data_list)
|
|
139
|
+
# sort dataframe by severity
|
|
140
|
+
df.sort_values(by=["severity"], inplace=True)
|
|
141
|
+
# reset and drop the index
|
|
142
|
+
df.reset_index(drop=True, inplace=True)
|
|
143
|
+
# convert the dataframe to an html table
|
|
144
|
+
output = df.to_html(header=True, index=False, justify="center", border=1)
|
|
145
|
+
return output
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def create_alert_assessment(
|
|
149
|
+
api: Api, parent_id: Optional[int] = None, parent_module: Optional[str] = None
|
|
150
|
+
) -> Optional[int]:
|
|
151
|
+
"""
|
|
152
|
+
Create Assessment containing SonarCloud alerts
|
|
153
|
+
:param Api api: API object
|
|
154
|
+
:param Optional[int] parent_id: Parent ID of the assessment, defaults to None
|
|
155
|
+
:param Optional[str] parent_module: Parent module of the assessment, defaults to None
|
|
156
|
+
:return: New Assessment ID, if created
|
|
157
|
+
:rtype: Optional[int]
|
|
158
|
+
"""
|
|
159
|
+
# create the assessment report HTML table
|
|
160
|
+
df_output = build_dataframes(api)
|
|
161
|
+
# build assessment model data
|
|
162
|
+
assessment_data = Assessment(
|
|
163
|
+
leadAssessorId=api.config["userId"],
|
|
164
|
+
title="SonarCloud Code Scan Assessment",
|
|
165
|
+
assessmentType="Control Testing",
|
|
166
|
+
plannedStart=get_current_datetime(),
|
|
167
|
+
plannedFinish=get_current_datetime(),
|
|
168
|
+
assessmentReport=df_output,
|
|
169
|
+
assessmentPlan="Complete the child issues created by the SonarCloud code scan results that were retrieved by the API. The assessment will fail if any high severity vulnerabilities has a days_elapsed value greater than or equal to 10 days.",
|
|
170
|
+
createdById=api.config["userId"],
|
|
171
|
+
dateCreated=get_current_datetime(),
|
|
172
|
+
lastUpdatedById=api.config["userId"],
|
|
173
|
+
dateLastUpdated=get_current_datetime(),
|
|
174
|
+
status="In Progress",
|
|
175
|
+
)
|
|
176
|
+
if parent_id and parent_module:
|
|
177
|
+
assessment_data.parentId = parent_id
|
|
178
|
+
assessment_data.parentModule = parent_module
|
|
179
|
+
# create vulnerability data list
|
|
180
|
+
vuln_data_list = build_data(api)
|
|
181
|
+
# if assessmentResult is changed to Pass / Fail then status has to be
|
|
182
|
+
# changed to complete and a completion date has to be passed
|
|
183
|
+
for vulnerability in vuln_data_list:
|
|
184
|
+
if vulnerability["severity"] == "CRITICAL" and vulnerability["days_elapsed"] >= 10:
|
|
185
|
+
assessment_data.status = "Complete"
|
|
186
|
+
assessment_data.actualFinish = get_current_datetime()
|
|
187
|
+
assessment_data.assessmentResult = "Fail"
|
|
188
|
+
|
|
189
|
+
# create a new assessment in RegScale
|
|
190
|
+
if new_assessment := assessment_data.create():
|
|
191
|
+
# log assessment creation result
|
|
192
|
+
api.logger.info("Assessment was created successfully")
|
|
193
|
+
return new_assessment.id
|
|
194
|
+
else:
|
|
195
|
+
api.logger.info("Assessment was not created")
|
|
196
|
+
return None
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def create_alert_issues(parent_id: Optional[int] = None, parent_module: Optional[str] = None) -> None:
|
|
200
|
+
"""
|
|
201
|
+
Create child issues from the alert assessment
|
|
202
|
+
:param Optional[int] parent_id: Parent ID record to associate the assessment to, defaults to None
|
|
203
|
+
:param Optional[str] parent_module: Parent module to associate the assessment to, defaults to None
|
|
204
|
+
:rtype: None
|
|
205
|
+
"""
|
|
206
|
+
# set environment and application configuration
|
|
207
|
+
app = Application()
|
|
208
|
+
api = Api()
|
|
209
|
+
# execute POST request and return new assessment ID
|
|
210
|
+
assessment_id = create_alert_assessment(api=api, parent_id=parent_id, parent_module=parent_module)
|
|
211
|
+
|
|
212
|
+
# create vulnerability data list
|
|
213
|
+
vuln_data_list = build_data(api)
|
|
214
|
+
# loop through each vulnerability alert in the list
|
|
215
|
+
for vulnerability in vuln_data_list:
|
|
216
|
+
# create issue model
|
|
217
|
+
issue_data = Issue(
|
|
218
|
+
title="Sonarcloud Code Scan", # Required
|
|
219
|
+
dateCreated=get_current_datetime("%Y-%m-%dT%H:%M:%S"),
|
|
220
|
+
description=vulnerability["message"],
|
|
221
|
+
severityLevel=Issue.assign_severity(vulnerability["severity"]), # Required
|
|
222
|
+
issueOwnerId=app.config["userId"], # Required
|
|
223
|
+
dueDate=get_current_datetime(),
|
|
224
|
+
identification="Code scan assessment",
|
|
225
|
+
status="Open",
|
|
226
|
+
assessmentId=assessment_id,
|
|
227
|
+
createdBy=app.config["userId"],
|
|
228
|
+
lastUpdatedById=app.config["userId"],
|
|
229
|
+
dateLastUpdated=get_current_datetime(),
|
|
230
|
+
parentId=assessment_id,
|
|
231
|
+
parentModule="assessments",
|
|
232
|
+
)
|
|
233
|
+
# create assessment child issue via POST
|
|
234
|
+
iss = api.post(
|
|
235
|
+
f'{app.config["domain"]}/api/issues',
|
|
236
|
+
json=issue_data.dict(),
|
|
237
|
+
)
|
|
238
|
+
# log issue creation result
|
|
239
|
+
if iss.ok:
|
|
240
|
+
logger.info("Issue created successfully.")
|
|
241
|
+
else:
|
|
242
|
+
logger.info("Issue was not created.")
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@click.group()
|
|
246
|
+
def sonarcloud() -> None:
|
|
247
|
+
"""
|
|
248
|
+
Create an assessment and child issues in RegScale from SonarCloud alerts.
|
|
249
|
+
"""
|
|
250
|
+
pass
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
@sonarcloud.command(name="sync_alerts")
|
|
254
|
+
@regscale_id(required=False, default=None)
|
|
255
|
+
@regscale_module(required=False, default=None)
|
|
256
|
+
def create_alerts(regscale_id: Optional[int] = None, regscale_module: Optional[str] = None) -> None:
|
|
257
|
+
"""
|
|
258
|
+
Create a child assessment and child issues in RegScale from SonarCloud alerts.
|
|
259
|
+
"""
|
|
260
|
+
create_alert_issues(regscale_id, regscale_module)
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""SQL Server integration for the CLI that allows for executing SQL queries"""
|
|
4
|
+
import os
|
|
5
|
+
from datetime import datetime, timedelta
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
|
|
11
|
+
from regscale.core.app.api import Api
|
|
12
|
+
from regscale.core.app.application import Application
|
|
13
|
+
from regscale.core.app.internal.workflow import create_regscale_workflow_from_template
|
|
14
|
+
from regscale.core.app.logz import create_logger
|
|
15
|
+
from regscale.core.app.utils.app_utils import (
|
|
16
|
+
check_file_path,
|
|
17
|
+
check_license,
|
|
18
|
+
create_progress_object,
|
|
19
|
+
get_current_datetime,
|
|
20
|
+
)
|
|
21
|
+
from regscale.core.app.utils.regscale_utils import (
|
|
22
|
+
verify_provided_module,
|
|
23
|
+
)
|
|
24
|
+
from regscale.models.app_models.click import regscale_id, regscale_module
|
|
25
|
+
from regscale.models.regscale_models import Assessment, File
|
|
26
|
+
|
|
27
|
+
job_progress = create_progress_object()
|
|
28
|
+
logger = create_logger()
|
|
29
|
+
# SQL query
|
|
30
|
+
sql_query = """
|
|
31
|
+
SELECT p.name AS [LoginName], r.name AS [RoleName]
|
|
32
|
+
FROM sys.server_principals r
|
|
33
|
+
JOIN sys.server_role_members m ON r.principal_id = m.role_principal_id
|
|
34
|
+
JOIN sys.server_principals p ON p.principal_id = m.member_principal_id
|
|
35
|
+
WHERE r.type = 'R' AND r.name
|
|
36
|
+
IN (N'sysadmin', N'db_owner', N'securityadmin')
|
|
37
|
+
and p.is_disabled = 0
|
|
38
|
+
ORDER BY p.name;
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@click.group()
|
|
43
|
+
def sqlserver():
|
|
44
|
+
"""sqlserver integration to pull admin users \
|
|
45
|
+
report via trusted connection."""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@sqlserver.command("admins_report")
|
|
49
|
+
@click.option(
|
|
50
|
+
"--workflow_template_id",
|
|
51
|
+
"-w",
|
|
52
|
+
type=click.INT,
|
|
53
|
+
help="Regscale workflow template ID",
|
|
54
|
+
required=True,
|
|
55
|
+
prompt=True,
|
|
56
|
+
)
|
|
57
|
+
@click.option(
|
|
58
|
+
"--output_dir",
|
|
59
|
+
"-o",
|
|
60
|
+
help="Output directory to save the report. Defaults to sqlserver_reports",
|
|
61
|
+
type=click.Path(exists=False, file_okay=False, dir_okay=True, writable=True),
|
|
62
|
+
default=Path("sqlserver_reports"),
|
|
63
|
+
prompt=False,
|
|
64
|
+
)
|
|
65
|
+
@click.option(
|
|
66
|
+
"--query_file",
|
|
67
|
+
"-q",
|
|
68
|
+
help="Path to a SQL query file.",
|
|
69
|
+
type=click.Path(exists=True, file_okay=True, dir_okay=False, readable=True),
|
|
70
|
+
)
|
|
71
|
+
@click.option(
|
|
72
|
+
"--server",
|
|
73
|
+
"-s",
|
|
74
|
+
required=True,
|
|
75
|
+
default=os.getenv("sqlServer"),
|
|
76
|
+
help="SQL Server host.",
|
|
77
|
+
)
|
|
78
|
+
@click.option(
|
|
79
|
+
"--database",
|
|
80
|
+
"-d",
|
|
81
|
+
required=True,
|
|
82
|
+
default=os.getenv("sqlServerDbName"),
|
|
83
|
+
help="Database name.",
|
|
84
|
+
)
|
|
85
|
+
@click.option(
|
|
86
|
+
"--port",
|
|
87
|
+
"-p",
|
|
88
|
+
required=True,
|
|
89
|
+
default=os.getenv("sqlServerPort"),
|
|
90
|
+
help="Database Port number.",
|
|
91
|
+
)
|
|
92
|
+
@click.option("--username", "-u", default=os.getenv("sqlServerUser"), help="Username.")
|
|
93
|
+
@click.option("--password", "-pwd", default=os.getenv("sqlServerPassword"), help="Password.")
|
|
94
|
+
@regscale_id()
|
|
95
|
+
@regscale_module()
|
|
96
|
+
@click.option(
|
|
97
|
+
"--output_file",
|
|
98
|
+
"-f",
|
|
99
|
+
help=f"Desired output file name. Defaults to RegScale_CLI_SQL_Report_{datetime.now().strftime('%Y%m%d')}",
|
|
100
|
+
type=click.STRING,
|
|
101
|
+
default=f"RegScale_CLI_SQL_Report_{datetime.now().strftime('%Y%m%d')}",
|
|
102
|
+
prompt=False,
|
|
103
|
+
)
|
|
104
|
+
def generate_report(
|
|
105
|
+
workflow_template_id: int,
|
|
106
|
+
output_dir: str,
|
|
107
|
+
output_file: str,
|
|
108
|
+
server: str,
|
|
109
|
+
database: str,
|
|
110
|
+
port: int,
|
|
111
|
+
username: str,
|
|
112
|
+
password: str,
|
|
113
|
+
regscale_id: int,
|
|
114
|
+
regscale_module: str,
|
|
115
|
+
query_file: Path,
|
|
116
|
+
) -> None:
|
|
117
|
+
"""Execute SQL query and save the data as a .csv report."""
|
|
118
|
+
generate_and_save_report(
|
|
119
|
+
workflow_template_id,
|
|
120
|
+
output_dir,
|
|
121
|
+
query_file,
|
|
122
|
+
server,
|
|
123
|
+
database,
|
|
124
|
+
port,
|
|
125
|
+
username,
|
|
126
|
+
password,
|
|
127
|
+
regscale_id,
|
|
128
|
+
regscale_module,
|
|
129
|
+
output_file,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def generate_and_save_report(
|
|
134
|
+
workflow_template_id: int,
|
|
135
|
+
output_dir: str,
|
|
136
|
+
query_file: Path,
|
|
137
|
+
server: str,
|
|
138
|
+
database: str,
|
|
139
|
+
port: int,
|
|
140
|
+
username: str,
|
|
141
|
+
password: str,
|
|
142
|
+
regscale_id: int,
|
|
143
|
+
regscale_module: str,
|
|
144
|
+
output_file: str = f"RegScale_CLI_SQL_Report_{datetime.now().strftime('%Y%m%d')}",
|
|
145
|
+
) -> None:
|
|
146
|
+
"""
|
|
147
|
+
:param int workflow_template_id: RegScale workflow template ID
|
|
148
|
+
:param str output_dir: Output directory
|
|
149
|
+
:param Path query_file: SQL query file
|
|
150
|
+
:param str server: SQL Server name
|
|
151
|
+
:param str database: Database name
|
|
152
|
+
:param int port: Port number
|
|
153
|
+
:param str username: Username
|
|
154
|
+
:param str password: Password
|
|
155
|
+
:param int regscale_id: RegScale module Id
|
|
156
|
+
:param str regscale_module: RegScale module name
|
|
157
|
+
:param str output_file: Output file name, defaults to RegScale_CLI_SQL_Report_{datetime.now().strftime('%Y%m%d')}
|
|
158
|
+
:rtype: None
|
|
159
|
+
"""
|
|
160
|
+
import pandas as pd # Optimize import performance
|
|
161
|
+
|
|
162
|
+
app = check_license()
|
|
163
|
+
|
|
164
|
+
# see if provided RegScale Module is an accepted option
|
|
165
|
+
verify_provided_module(regscale_module)
|
|
166
|
+
|
|
167
|
+
# Build the connection string
|
|
168
|
+
conn_str = build_connection_string(server, database, port, username, password)
|
|
169
|
+
import pyodbc
|
|
170
|
+
|
|
171
|
+
with pyodbc.connect(conn_str) as cnxn:
|
|
172
|
+
cursor = cnxn.cursor()
|
|
173
|
+
if query_file:
|
|
174
|
+
sql_query = _get_query_from_file(query_file)
|
|
175
|
+
cursor.execute(sql_query)
|
|
176
|
+
rows = cursor.fetchall()
|
|
177
|
+
# Create a DataFrame from the rows
|
|
178
|
+
df = pd.DataFrame.from_records(rows, columns=[column[0] for column in cursor.description])
|
|
179
|
+
|
|
180
|
+
if not df.empty:
|
|
181
|
+
# Convert the DataFrame to an HTML table
|
|
182
|
+
report = df.to_html(index=False)
|
|
183
|
+
|
|
184
|
+
# Save the DataFrame to a CSV file
|
|
185
|
+
new_file = f"{output_file}.csv"
|
|
186
|
+
# Specify the directory where you want to save the CSV file
|
|
187
|
+
|
|
188
|
+
# Create the directory if it does not exist
|
|
189
|
+
check_file_path(output_dir)
|
|
190
|
+
|
|
191
|
+
full_path = output_dir / new_file
|
|
192
|
+
# Save the DataFrame to a CSV file in the specified directory
|
|
193
|
+
df.to_csv(full_path, index=False)
|
|
194
|
+
title = f"Sql Server Report assessment {regscale_module.title()}-{regscale_id}"
|
|
195
|
+
description = f"Sql Server Report assessment {regscale_module.title()}-{regscale_id}"
|
|
196
|
+
new_assessment_id = create_and_save_assessment(
|
|
197
|
+
report,
|
|
198
|
+
[full_path],
|
|
199
|
+
regscale_id,
|
|
200
|
+
regscale_module,
|
|
201
|
+
title=title,
|
|
202
|
+
description=description,
|
|
203
|
+
app=app,
|
|
204
|
+
)
|
|
205
|
+
logger.debug(f"New assessment created here is the id: {new_assessment_id}")
|
|
206
|
+
if new_assessment_id and workflow_template_id:
|
|
207
|
+
create_regscale_workflow_from_template(
|
|
208
|
+
new_assessment_id,
|
|
209
|
+
template_id=workflow_template_id,
|
|
210
|
+
)
|
|
211
|
+
else:
|
|
212
|
+
logger.info(f"No data found for query: {sql_query}.")
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _get_query_from_file(file_path: str) -> str:
|
|
216
|
+
"""
|
|
217
|
+
Get the SQL query from a file.
|
|
218
|
+
:param str file_path: Path to SQL query file
|
|
219
|
+
:return: SQL query
|
|
220
|
+
:rtype: str
|
|
221
|
+
"""
|
|
222
|
+
with open(file_path, "r") as file:
|
|
223
|
+
query = file.read()
|
|
224
|
+
return query
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def build_connection_string(
|
|
228
|
+
server: str,
|
|
229
|
+
database: str,
|
|
230
|
+
port: int,
|
|
231
|
+
username: Optional[str],
|
|
232
|
+
password: Optional[str],
|
|
233
|
+
) -> str:
|
|
234
|
+
"""
|
|
235
|
+
Build the connection string for the SQL Server.
|
|
236
|
+
:param str server: SQL Server name
|
|
237
|
+
:param str database: Database name
|
|
238
|
+
:param int port: Port number for the SQL Server
|
|
239
|
+
:param Optional[str] username: Database Username optional
|
|
240
|
+
:param Optional[str] password: Database Password optional
|
|
241
|
+
:return: Connection string
|
|
242
|
+
:rtype: str
|
|
243
|
+
"""
|
|
244
|
+
if username and password:
|
|
245
|
+
conn_str = (
|
|
246
|
+
r"DRIVER={ODBC Driver 17 for SQL Server};"
|
|
247
|
+
r"SERVER=" + server + ";"
|
|
248
|
+
r"DATABASE=" + database + ";"
|
|
249
|
+
r"PORT=" + str(port) + ";"
|
|
250
|
+
r"UID=" + username + ";"
|
|
251
|
+
r"PWD=" + password + ";"
|
|
252
|
+
r"TrustServerCertificate=yes;"
|
|
253
|
+
r"TIMEOUT=30;"
|
|
254
|
+
# Set the login timeout to 30 seconds
|
|
255
|
+
)
|
|
256
|
+
else:
|
|
257
|
+
conn_str = (
|
|
258
|
+
r"DRIVER={ODBC Driver 17 for SQL Server};"
|
|
259
|
+
r"SERVER=" + server + ";"
|
|
260
|
+
r"DATABASE=" + database + ";"
|
|
261
|
+
r"PORT=" + str(port) + ";"
|
|
262
|
+
r"Trusted_Connection=yes;"
|
|
263
|
+
)
|
|
264
|
+
return conn_str
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def calculate_finish_date(current_date: datetime, days: int) -> str:
|
|
268
|
+
"""
|
|
269
|
+
Calculate finish date for Assessment by adding days to current date
|
|
270
|
+
:param datetime current_date: Date to start with
|
|
271
|
+
:param int days: # of days to add to current date
|
|
272
|
+
:return: String representation of finish date
|
|
273
|
+
:rtype: str
|
|
274
|
+
"""
|
|
275
|
+
return (current_date + timedelta(days=days)).strftime("%Y-%m-%dT%H:%M:%S")
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def create_assessment_object(
|
|
279
|
+
app: Application,
|
|
280
|
+
report: str,
|
|
281
|
+
regscale_id: int,
|
|
282
|
+
regscale_module: str,
|
|
283
|
+
title: str,
|
|
284
|
+
description: str,
|
|
285
|
+
) -> Assessment:
|
|
286
|
+
"""
|
|
287
|
+
Create a RegScale assessment object
|
|
288
|
+
:param Application app: Application object
|
|
289
|
+
:param str report: Assessment report
|
|
290
|
+
:param int regscale_id: RegScale ID
|
|
291
|
+
:param str regscale_module: RegScale module
|
|
292
|
+
:param str title: Assessment title
|
|
293
|
+
:param str description: Assessment description
|
|
294
|
+
:return: Assessment object
|
|
295
|
+
:rtype: Assessment
|
|
296
|
+
"""
|
|
297
|
+
finish_date = calculate_finish_date(datetime.now(), app.config["assessmentDays"])
|
|
298
|
+
status = "Scheduled"
|
|
299
|
+
new_assessment = Assessment(
|
|
300
|
+
leadAssessorId=app.config["userId"],
|
|
301
|
+
title=title,
|
|
302
|
+
assessmentType="Control Testing",
|
|
303
|
+
plannedStart=get_current_datetime(),
|
|
304
|
+
plannedFinish=finish_date,
|
|
305
|
+
assessmentReport=report,
|
|
306
|
+
assessmentPlan=description,
|
|
307
|
+
createdById=app.config["userId"],
|
|
308
|
+
dateCreated=get_current_datetime(),
|
|
309
|
+
lastUpdatedById=app.config["userId"],
|
|
310
|
+
dateLastUpdated=get_current_datetime(),
|
|
311
|
+
parentModule=regscale_module,
|
|
312
|
+
parentId=regscale_id,
|
|
313
|
+
status=status,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
new_assessment.actualFinish = "true"
|
|
317
|
+
new_assessment.assessmentResult = "Pass"
|
|
318
|
+
return new_assessment
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def upload_files_to_assessment(api: Api, assessment_id: int, files: list) -> None:
|
|
322
|
+
"""
|
|
323
|
+
Upload files to the new RegScale Assessment
|
|
324
|
+
:param Api api: Api object
|
|
325
|
+
:param int assessment_id: RegScale assessment id
|
|
326
|
+
:param list files: List of files to upload to RegScale assessment
|
|
327
|
+
:rtype: None
|
|
328
|
+
"""
|
|
329
|
+
upload_files = job_progress.add_task("[#0866b4]Uploading files to the new RegScale Assessment...", total=len(files))
|
|
330
|
+
for new_file in files:
|
|
331
|
+
new_file_upload = File.upload_file_to_regscale(
|
|
332
|
+
file_name=new_file,
|
|
333
|
+
parent_id=assessment_id,
|
|
334
|
+
parent_module="assessments",
|
|
335
|
+
api=api,
|
|
336
|
+
)
|
|
337
|
+
if new_file_upload:
|
|
338
|
+
job_progress.update(upload_files, advance=1)
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def create_and_save_assessment(
|
|
342
|
+
report: str,
|
|
343
|
+
files: list,
|
|
344
|
+
regscale_id: int,
|
|
345
|
+
regscale_module: str,
|
|
346
|
+
title: str,
|
|
347
|
+
description: str,
|
|
348
|
+
app: Application,
|
|
349
|
+
) -> int:
|
|
350
|
+
"""
|
|
351
|
+
Create a new RegScale Assessment and upload the report and files to it
|
|
352
|
+
:param str report: Report to upload to assessment
|
|
353
|
+
:param list files: List of files to upload to assessment
|
|
354
|
+
:param int regscale_id: RegScale id
|
|
355
|
+
:param str regscale_module: RegScale module
|
|
356
|
+
:param str title: Assessment title
|
|
357
|
+
:param str description: Assessment description
|
|
358
|
+
:param Application app: Application object
|
|
359
|
+
:return:RegScale assessment id
|
|
360
|
+
:rtype: int
|
|
361
|
+
"""
|
|
362
|
+
api = Api()
|
|
363
|
+
new_assessment = create_assessment_object(app, report, regscale_id, regscale_module, title, description)
|
|
364
|
+
create_assessment = job_progress.add_task("[#21a5bb]Creating assessment in RegScale...", total=1)
|
|
365
|
+
if new_assessment_id := new_assessment.insert_assessment(app=app).id:
|
|
366
|
+
logger.info(f"created new RegScale Assessment with id of {new_assessment_id}")
|
|
367
|
+
job_progress.update(create_assessment, advance=1)
|
|
368
|
+
upload_files_to_assessment(api, new_assessment_id, files)
|
|
369
|
+
return new_assessment_id
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""STIG Mapper commands."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from regscale.models import regscale_id, regscale_module, Asset
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@click.group(name="stig_mapper")
|
|
13
|
+
def stig_mapper():
|
|
14
|
+
"""Map data from STIGs to RegScale."""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@stig_mapper.command(name="run")
|
|
18
|
+
@click.option(
|
|
19
|
+
"--json-file", help="Path to the JSON file with mapping rules", required=True, type=click.Path(exists=True)
|
|
20
|
+
)
|
|
21
|
+
@regscale_id()
|
|
22
|
+
@regscale_module()
|
|
23
|
+
def run(json_file: str, regscale_id: int, regscale_module: str):
|
|
24
|
+
"""
|
|
25
|
+
Map STIGs from a .json file to assets in RegScale.
|
|
26
|
+
"""
|
|
27
|
+
from regscale.integrations.commercial.stig_mapper_integration.mapping_engine import StigMappingEngine as STIGMapper
|
|
28
|
+
from os import path
|
|
29
|
+
|
|
30
|
+
if not path.exists(json_file):
|
|
31
|
+
logger.error(f"File {json_file} does not exist.")
|
|
32
|
+
return
|
|
33
|
+
stig_mapper = STIGMapper(json_file)
|
|
34
|
+
assets = Asset.get_all_by_parent(parent_id=regscale_id, parent_module=regscale_module)
|
|
35
|
+
asset_mappings = []
|
|
36
|
+
for asset in assets:
|
|
37
|
+
asset_mappings.append(stig_mapper.map_associated_stigs_to_asset(asset=asset, ssp_id=regscale_id))
|
|
38
|
+
logger.info(f"Created {len(asset_mappings)} new asset mappings")
|