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,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module contains the Click command group for Sicura.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
from regscale.models import regscale_id
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger("regscale")
|
|
12
|
+
console = Console()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@click.group()
|
|
16
|
+
def sicura():
|
|
17
|
+
"""
|
|
18
|
+
Sicura Integration
|
|
19
|
+
|
|
20
|
+
Commands for interacting with Sicura security scanning platform.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@sicura.command(name="sync_assets")
|
|
25
|
+
@regscale_id(help="RegScale will create and update assets as children of this record.")
|
|
26
|
+
def sync_assets(regscale_id):
|
|
27
|
+
"""
|
|
28
|
+
Sync Sicura assets to RegScale.
|
|
29
|
+
|
|
30
|
+
Fetches all devices from Sicura and synchronizes them as assets into RegScale.
|
|
31
|
+
"""
|
|
32
|
+
try:
|
|
33
|
+
from regscale.integrations.commercial.sicura.scanner import SicuraIntegration
|
|
34
|
+
|
|
35
|
+
integration = SicuraIntegration(
|
|
36
|
+
plan_id=regscale_id,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
with console.status("[bold green]Syncing assets from Sicura to RegScale..."):
|
|
40
|
+
# Using import_assets method which handles the synchronization
|
|
41
|
+
integration.sync_assets(plan_id=regscale_id)
|
|
42
|
+
|
|
43
|
+
console.print("[bold green]Asset synchronization complete.")
|
|
44
|
+
|
|
45
|
+
except Exception as e:
|
|
46
|
+
logger.error(f"Error syncing assets: {e}", exc_info=True)
|
|
47
|
+
console.print(f"[bold red]Error syncing assets: {e}")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@sicura.command(name="sync_findings")
|
|
51
|
+
@regscale_id(help="RegScale will create and update findings as children of this record.")
|
|
52
|
+
def sync_findings(regscale_id):
|
|
53
|
+
"""
|
|
54
|
+
Sync Sicura findings to RegScale.
|
|
55
|
+
|
|
56
|
+
Fetches all scan results from Sicura and synchronizes them as findings into RegScale.
|
|
57
|
+
"""
|
|
58
|
+
try:
|
|
59
|
+
from regscale.integrations.commercial.sicura.scanner import SicuraIntegration
|
|
60
|
+
|
|
61
|
+
integration = SicuraIntegration(
|
|
62
|
+
plan_id=regscale_id,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
with console.status("[bold green]Syncing findings from Sicura to RegScale..."):
|
|
66
|
+
# Using import_findings method which handles the synchronization
|
|
67
|
+
integration.sync_findings(plan_id=regscale_id)
|
|
68
|
+
|
|
69
|
+
console.print("[bold green]Finding synchronization complete.")
|
|
70
|
+
|
|
71
|
+
except Exception as e:
|
|
72
|
+
logger.error(f"Error syncing findings: {e}", exc_info=True)
|
|
73
|
+
console.print(f"[bold red]Error syncing findings: {e}")
|
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
RegScale Sicura Integration
|
|
5
|
+
"""
|
|
6
|
+
import datetime
|
|
7
|
+
from typing import Generator, Iterator, Any
|
|
8
|
+
|
|
9
|
+
from regscale.core.utils.date import date_str
|
|
10
|
+
from regscale.integrations.commercial.sicura.api import SicuraAPI, ScanReport, SicuraProfile, Device, ScanResult
|
|
11
|
+
from regscale.integrations.scanner_integration import (
|
|
12
|
+
logger,
|
|
13
|
+
IntegrationFinding,
|
|
14
|
+
ScannerIntegration,
|
|
15
|
+
IntegrationAsset,
|
|
16
|
+
ScannerIntegrationType,
|
|
17
|
+
issue_due_date,
|
|
18
|
+
)
|
|
19
|
+
from regscale.models import regscale_models
|
|
20
|
+
from regscale.models.regscale_models import AssetType
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SicuraIntegration(ScannerIntegration):
|
|
24
|
+
"""
|
|
25
|
+
Sicura Integration for RegScale
|
|
26
|
+
|
|
27
|
+
This integration fetches assets and scan findings from Sicura
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
options_map_assets_to_components = True
|
|
31
|
+
import_closed_findings = False
|
|
32
|
+
|
|
33
|
+
title = "Sicura"
|
|
34
|
+
type = ScannerIntegrationType.CHECKLIST
|
|
35
|
+
|
|
36
|
+
# Map Sicura scan result states to RegScale checklist statuses
|
|
37
|
+
checklist_status_map = {
|
|
38
|
+
"pass": regscale_models.ChecklistStatus.PASS,
|
|
39
|
+
"fail": regscale_models.ChecklistStatus.FAIL,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# Map severity levels
|
|
43
|
+
finding_severity_map = {
|
|
44
|
+
"high": regscale_models.IssueSeverity.High,
|
|
45
|
+
"medium": regscale_models.IssueSeverity.Moderate,
|
|
46
|
+
"low": regscale_models.IssueSeverity.Low,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
def __init__(self, *args, **kwargs):
|
|
50
|
+
"""
|
|
51
|
+
Initialize the Sicura Integration
|
|
52
|
+
|
|
53
|
+
:param args: Arguments to pass to the parent class
|
|
54
|
+
:param kwargs: Keyword arguments to pass to the parent class
|
|
55
|
+
"""
|
|
56
|
+
super().__init__(*args, **kwargs)
|
|
57
|
+
self.api = SicuraAPI()
|
|
58
|
+
|
|
59
|
+
def fetch_findings(self, **kwargs) -> Generator[IntegrationFinding, None, None]:
|
|
60
|
+
"""
|
|
61
|
+
Fetches findings from Sicura API
|
|
62
|
+
|
|
63
|
+
:param kwargs: Additional arguments
|
|
64
|
+
:yields: IntegrationFinding objects
|
|
65
|
+
:return: Generator of IntegrationFinding objects
|
|
66
|
+
:rtype: Generator[IntegrationFinding, None, None]
|
|
67
|
+
"""
|
|
68
|
+
logger.info("Fetching findings from Sicura...")
|
|
69
|
+
|
|
70
|
+
# Get all devices
|
|
71
|
+
devices = kwargs.get("devices", self.api.get_devices())
|
|
72
|
+
|
|
73
|
+
if not devices:
|
|
74
|
+
logger.warning("No devices found in Sicura")
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
self.num_findings_to_process = 0
|
|
78
|
+
findings_count = 0
|
|
79
|
+
|
|
80
|
+
# Process each device
|
|
81
|
+
for device in devices:
|
|
82
|
+
for finding in self._process_device_findings(device):
|
|
83
|
+
findings_count += 1
|
|
84
|
+
yield finding
|
|
85
|
+
|
|
86
|
+
self.num_findings_to_process = findings_count
|
|
87
|
+
|
|
88
|
+
def _process_device_findings(self, device: Device) -> Generator[IntegrationFinding, None, None]:
|
|
89
|
+
"""
|
|
90
|
+
Process findings for a single device
|
|
91
|
+
|
|
92
|
+
:param Device device: The device to process
|
|
93
|
+
:yield: IntegrationFinding objects
|
|
94
|
+
:rtype: Generator[IntegrationFinding, None, None]
|
|
95
|
+
"""
|
|
96
|
+
logger.info(f"Fetching scan results for device: {device.fqdn}")
|
|
97
|
+
if not device.fqdn:
|
|
98
|
+
logger.warning(f"Device {device.name} has no FQDN, skipping")
|
|
99
|
+
return
|
|
100
|
+
|
|
101
|
+
# Profiles to scan
|
|
102
|
+
profiles = [SicuraProfile.I_MISSION_CRITICAL_CLASSIFIED, SicuraProfile.LEVEL_1_SERVER]
|
|
103
|
+
|
|
104
|
+
for profile in profiles:
|
|
105
|
+
yield from self._process_profile_findings(device, profile)
|
|
106
|
+
|
|
107
|
+
def _process_profile_findings(
|
|
108
|
+
self, device: Device, profile: SicuraProfile
|
|
109
|
+
) -> Generator[IntegrationFinding, None, None]:
|
|
110
|
+
"""
|
|
111
|
+
Process findings for a device with a specific profile
|
|
112
|
+
|
|
113
|
+
:param Device device: The device to process
|
|
114
|
+
:param SicuraProfile profile: The profile to process
|
|
115
|
+
:yield: IntegrationFinding objects
|
|
116
|
+
:rtype: Generator[IntegrationFinding, None, None]
|
|
117
|
+
"""
|
|
118
|
+
scan_report = self.api.get_scan_results(fqdn=device.fqdn, profile=profile)
|
|
119
|
+
|
|
120
|
+
if not scan_report:
|
|
121
|
+
logger.warning(f"No scan results found for device: {device.fqdn} with profile: {profile}")
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
# Process scan results based on the report type
|
|
125
|
+
if isinstance(scan_report, ScanReport):
|
|
126
|
+
yield from self._process_scan_report_findings(device, scan_report.scans)
|
|
127
|
+
elif isinstance(scan_report, dict) and scan_report.get("scans"):
|
|
128
|
+
yield from self._process_scan_report_findings(device, scan_report.get("scans", []))
|
|
129
|
+
|
|
130
|
+
def _process_scan_report_findings(self, device: Device, scans: list) -> Generator[IntegrationFinding, None, None]:
|
|
131
|
+
"""
|
|
132
|
+
Process findings from a scan report
|
|
133
|
+
|
|
134
|
+
:param Device device: The device being scanned
|
|
135
|
+
:param list scans: The list of scans to process
|
|
136
|
+
:yield: IntegrationFinding objects
|
|
137
|
+
:rtype: Generator[IntegrationFinding, None, None]
|
|
138
|
+
"""
|
|
139
|
+
for scan in scans:
|
|
140
|
+
yield from self.parse_finding(device, scan)
|
|
141
|
+
|
|
142
|
+
def parse_finding(
|
|
143
|
+
self,
|
|
144
|
+
device: Device,
|
|
145
|
+
scan: Any,
|
|
146
|
+
) -> Generator[IntegrationFinding, None, None]:
|
|
147
|
+
"""
|
|
148
|
+
Creates and yields IntegrationFinding objects from Sicura scan results, one per CCI reference
|
|
149
|
+
|
|
150
|
+
:param Device device: The device object
|
|
151
|
+
:param Any scan: The scan data
|
|
152
|
+
:yield: IntegrationFinding objects
|
|
153
|
+
:rtype: Generator[IntegrationFinding, None, None]
|
|
154
|
+
"""
|
|
155
|
+
# Extract basic information from device and scan
|
|
156
|
+
asset_identifier = device.fqdn
|
|
157
|
+
platform = device.platforms
|
|
158
|
+
|
|
159
|
+
# Extract scan data
|
|
160
|
+
scan_data = self._extract_scan_data(scan)
|
|
161
|
+
title = scan_data["title"]
|
|
162
|
+
ce_name = scan_data["ce_name"]
|
|
163
|
+
result = scan_data["result"]
|
|
164
|
+
description = scan_data["description"]
|
|
165
|
+
state = scan_data["state"]
|
|
166
|
+
state_reason = scan_data["state_reason"]
|
|
167
|
+
controls = scan_data["controls"]
|
|
168
|
+
|
|
169
|
+
# Extract control references
|
|
170
|
+
cci_refs, srg_refs = self._extract_control_refs(controls)
|
|
171
|
+
|
|
172
|
+
# Determine severity and due date
|
|
173
|
+
severity = self._determine_severity(title)
|
|
174
|
+
created_date = date_str(datetime.datetime.now())
|
|
175
|
+
due_date = issue_due_date(severity, created_date, title=self.title)
|
|
176
|
+
|
|
177
|
+
# Common mitigation recommendation
|
|
178
|
+
mitigation = f"Fix the issues identified: {', '.join(state_reason) if state_reason else 'See description'}"
|
|
179
|
+
|
|
180
|
+
# If no CCI references, use empty string as the only CCI ref
|
|
181
|
+
if not cci_refs:
|
|
182
|
+
cci_refs = [""]
|
|
183
|
+
|
|
184
|
+
# Create a finding for each CCI reference
|
|
185
|
+
for cci_ref in cci_refs:
|
|
186
|
+
# Create a ScanResult object to hold the scan data
|
|
187
|
+
scan_result = ScanResult(
|
|
188
|
+
title=title,
|
|
189
|
+
ce_name=ce_name,
|
|
190
|
+
result=result,
|
|
191
|
+
description=description,
|
|
192
|
+
state=state,
|
|
193
|
+
state_reason=state_reason,
|
|
194
|
+
controls=controls,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
yield from self._create_finding_for_cci(
|
|
198
|
+
asset_identifier=asset_identifier,
|
|
199
|
+
platform=platform,
|
|
200
|
+
cci_ref=cci_ref,
|
|
201
|
+
scan_result=scan_result,
|
|
202
|
+
srg_refs=srg_refs,
|
|
203
|
+
severity=severity,
|
|
204
|
+
created_date=created_date,
|
|
205
|
+
due_date=due_date,
|
|
206
|
+
mitigation=mitigation,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
def _extract_scan_data(self, scan: Any) -> dict:
|
|
210
|
+
"""
|
|
211
|
+
Extract scan data from the scan object
|
|
212
|
+
|
|
213
|
+
:param Any scan: The scan object
|
|
214
|
+
:return: Dictionary with scan data
|
|
215
|
+
:rtype: dict
|
|
216
|
+
"""
|
|
217
|
+
if isinstance(scan, dict):
|
|
218
|
+
return {
|
|
219
|
+
"title": scan.get("title", ""),
|
|
220
|
+
"ce_name": scan.get("ce_name", ""),
|
|
221
|
+
"result": scan.get("result", ""),
|
|
222
|
+
"description": scan.get("description", ""),
|
|
223
|
+
"state": scan.get("state", ""),
|
|
224
|
+
"state_reason": scan.get("state_reason", []),
|
|
225
|
+
"controls": scan.get("controls", {}),
|
|
226
|
+
}
|
|
227
|
+
else:
|
|
228
|
+
return {
|
|
229
|
+
"title": scan.title,
|
|
230
|
+
"ce_name": scan.ce_name,
|
|
231
|
+
"result": scan.result,
|
|
232
|
+
"description": scan.description,
|
|
233
|
+
"state": scan.state,
|
|
234
|
+
"state_reason": scan.state_reason,
|
|
235
|
+
"controls": scan.controls if hasattr(scan, "controls") else {},
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
def _extract_control_refs(self, controls: dict) -> tuple:
|
|
239
|
+
"""
|
|
240
|
+
Extract CCI and SRG references from controls
|
|
241
|
+
|
|
242
|
+
:param dict controls: The controls dictionary
|
|
243
|
+
:return: Tuple of (cci_refs, srg_refs)
|
|
244
|
+
:rtype: tuple
|
|
245
|
+
"""
|
|
246
|
+
cci_refs = []
|
|
247
|
+
srg_refs = []
|
|
248
|
+
|
|
249
|
+
for control_key, control_value in controls.items():
|
|
250
|
+
if control_key.startswith("cci:"):
|
|
251
|
+
# Extract CCI number (e.g., "cci:CCI-000366" -> "CCI-000366")
|
|
252
|
+
cci_ref = control_key.split(":", 1)[1] if ":" in control_key else control_key
|
|
253
|
+
cci_refs.append(cci_ref)
|
|
254
|
+
elif control_key.startswith("SRG-"):
|
|
255
|
+
srg_refs.append(control_key)
|
|
256
|
+
|
|
257
|
+
return cci_refs, srg_refs
|
|
258
|
+
|
|
259
|
+
def _determine_severity(self, title: str) -> regscale_models.IssueSeverity:
|
|
260
|
+
"""
|
|
261
|
+
Determine severity based on title
|
|
262
|
+
|
|
263
|
+
:param str title: The finding title
|
|
264
|
+
:return: Severity enum value
|
|
265
|
+
:rtype: regscale_models.IssueSeverity
|
|
266
|
+
"""
|
|
267
|
+
severity_text = "medium"
|
|
268
|
+
if "critical" in title.lower() or "cat i" in title.lower():
|
|
269
|
+
severity_text = "high"
|
|
270
|
+
elif "low" in title.lower() or "cat iii" in title.lower():
|
|
271
|
+
severity_text = "low"
|
|
272
|
+
|
|
273
|
+
return self.get_finding_severity(severity_text)
|
|
274
|
+
|
|
275
|
+
def _create_finding_for_cci(
|
|
276
|
+
self,
|
|
277
|
+
asset_identifier,
|
|
278
|
+
platform,
|
|
279
|
+
cci_ref,
|
|
280
|
+
scan_result: ScanResult,
|
|
281
|
+
srg_refs,
|
|
282
|
+
severity,
|
|
283
|
+
created_date,
|
|
284
|
+
due_date,
|
|
285
|
+
mitigation,
|
|
286
|
+
) -> Generator[IntegrationFinding, None, None]:
|
|
287
|
+
"""
|
|
288
|
+
Create a finding for a single CCI reference
|
|
289
|
+
|
|
290
|
+
:param str asset_identifier: The asset identifier
|
|
291
|
+
:param str platform: The platform
|
|
292
|
+
:param str cci_ref: The CCI reference
|
|
293
|
+
:param ScanResult scan_result: The scan result data
|
|
294
|
+
:param list srg_refs: The SRG references
|
|
295
|
+
:param regscale_models.IssueSeverity severity: The severity
|
|
296
|
+
:param str created_date: The created date
|
|
297
|
+
:param str due_date: The due date
|
|
298
|
+
:param str mitigation: The mitigation
|
|
299
|
+
:yield: IntegrationFinding objects
|
|
300
|
+
:rtype: Generator[IntegrationFinding, None, None]
|
|
301
|
+
"""
|
|
302
|
+
# Determine if this is a CCI finding or a regular finding
|
|
303
|
+
is_cci_finding = cci_ref != ""
|
|
304
|
+
|
|
305
|
+
# Extract values from scan_result
|
|
306
|
+
title = scan_result.title
|
|
307
|
+
ce_name = scan_result.ce_name
|
|
308
|
+
result = scan_result.result
|
|
309
|
+
description = scan_result.description
|
|
310
|
+
state = scan_result.state
|
|
311
|
+
state_reason = scan_result.state_reason
|
|
312
|
+
|
|
313
|
+
# Set title based on whether it's a CCI finding
|
|
314
|
+
finding_title = title if not is_cci_finding else f"{title} (CCI: {cci_ref})"
|
|
315
|
+
|
|
316
|
+
# Create results text
|
|
317
|
+
results = self._create_results_text(
|
|
318
|
+
title, ce_name, result, description, state, state_reason, cci_ref, srg_refs, is_cci_finding
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
# Create external ID
|
|
322
|
+
external_id = (
|
|
323
|
+
f"{ce_name}:{asset_identifier}" if not is_cci_finding else f"{ce_name}:{cci_ref}:{asset_identifier}"
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
# Create and yield the finding
|
|
327
|
+
yield IntegrationFinding(
|
|
328
|
+
asset_identifier=asset_identifier,
|
|
329
|
+
control_labels=[], # Empty list as controls will be mapped via other mechanisms
|
|
330
|
+
title=finding_title,
|
|
331
|
+
issue_title=finding_title,
|
|
332
|
+
category=ce_name,
|
|
333
|
+
severity=severity,
|
|
334
|
+
description=description,
|
|
335
|
+
status=regscale_models.IssueStatus.Open if result == "fail" else regscale_models.IssueStatus.Closed,
|
|
336
|
+
checklist_status=self.get_checklist_status(result),
|
|
337
|
+
external_id=external_id,
|
|
338
|
+
vulnerability_number=ce_name,
|
|
339
|
+
cci_ref=cci_ref,
|
|
340
|
+
rule_id=ce_name,
|
|
341
|
+
rule_version="1.0",
|
|
342
|
+
results=results,
|
|
343
|
+
recommendation_for_mitigation=mitigation,
|
|
344
|
+
comments="",
|
|
345
|
+
poam_comments="",
|
|
346
|
+
date_created=created_date,
|
|
347
|
+
due_date=due_date,
|
|
348
|
+
plugin_name=ce_name,
|
|
349
|
+
observations=f"Result: {result}, State: {state}",
|
|
350
|
+
gaps=description,
|
|
351
|
+
evidence=f"State reasons: {', '.join(state_reason) if state_reason else 'N/A'}",
|
|
352
|
+
impact="Security compliance impact",
|
|
353
|
+
baseline=platform,
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
def _create_results_text(
|
|
357
|
+
self, title, ce_name, result, description, state, state_reason, cci_ref, srg_refs, is_cci_finding
|
|
358
|
+
) -> str:
|
|
359
|
+
"""
|
|
360
|
+
Create the results text for a finding
|
|
361
|
+
|
|
362
|
+
:param str title: The finding title
|
|
363
|
+
:param str ce_name: The CE name
|
|
364
|
+
:param str result: The result
|
|
365
|
+
:param str description: The description
|
|
366
|
+
:param str state: The state
|
|
367
|
+
:param list state_reason: The state reason
|
|
368
|
+
:param str cci_ref: The CCI reference
|
|
369
|
+
:param list srg_refs: The SRG references
|
|
370
|
+
:param bool is_cci_finding: Whether this is a CCI finding
|
|
371
|
+
:return: The results text
|
|
372
|
+
:rtype: str
|
|
373
|
+
"""
|
|
374
|
+
# Create the results text with conditional CCI reference section
|
|
375
|
+
results_parts = [
|
|
376
|
+
f"Title: {title}",
|
|
377
|
+
f"Check: {ce_name}",
|
|
378
|
+
f"Result: {result}",
|
|
379
|
+
f"Description: {description}",
|
|
380
|
+
f"State: {state}",
|
|
381
|
+
f"State Reason: {', '.join(state_reason) if state_reason else 'N/A'}",
|
|
382
|
+
]
|
|
383
|
+
|
|
384
|
+
# Add CCI reference only if it exists
|
|
385
|
+
if is_cci_finding:
|
|
386
|
+
results_parts.append(f"CCI Reference: {cci_ref}")
|
|
387
|
+
|
|
388
|
+
# Always add SRG references
|
|
389
|
+
results_parts.append(f"SRG References: {', '.join(srg_refs)}")
|
|
390
|
+
|
|
391
|
+
# Join all parts with newlines
|
|
392
|
+
return "\n".join(results_parts)
|
|
393
|
+
|
|
394
|
+
def fetch_assets(self, **kwargs) -> Iterator[IntegrationAsset]:
|
|
395
|
+
"""
|
|
396
|
+
Fetches assets from Sicura API
|
|
397
|
+
|
|
398
|
+
:param kwargs: Additional arguments
|
|
399
|
+
:yield: IntegrationAsset objects
|
|
400
|
+
:return: Iterator of IntegrationAsset objects
|
|
401
|
+
:rtype: Iterator[IntegrationAsset]
|
|
402
|
+
"""
|
|
403
|
+
logger.info("Fetching assets from Sicura...")
|
|
404
|
+
|
|
405
|
+
# Get all devices
|
|
406
|
+
pending_devices = self.api.get_pending_devices()
|
|
407
|
+
for pending_device in pending_devices:
|
|
408
|
+
print(f"Pending device: {pending_device}")
|
|
409
|
+
self.api.accept_pending_device(pending_device.id)
|
|
410
|
+
task_id = self.api.create_scan_task(
|
|
411
|
+
device_id=pending_device.id,
|
|
412
|
+
platform=pending_device.platform,
|
|
413
|
+
profile=SicuraProfile.I_MISSION_CRITICAL_CLASSIFIED,
|
|
414
|
+
)
|
|
415
|
+
if task_id:
|
|
416
|
+
self.api.wait_for_scan_results(
|
|
417
|
+
task_id=task_id,
|
|
418
|
+
fqdn=pending_device.fqdn,
|
|
419
|
+
platform=pending_device.platform,
|
|
420
|
+
profile=SicuraProfile.I_MISSION_CRITICAL_CLASSIFIED,
|
|
421
|
+
)
|
|
422
|
+
else:
|
|
423
|
+
logger.warning(f"Failed to create scan task for device {pending_device.fqdn}")
|
|
424
|
+
continue # Continue to next device if creating scan task failed
|
|
425
|
+
|
|
426
|
+
task_id = self.api.create_scan_task(
|
|
427
|
+
device_id=pending_device.id, platform=pending_device.platform, profile=SicuraProfile.LEVEL_1_SERVER
|
|
428
|
+
)
|
|
429
|
+
if task_id:
|
|
430
|
+
self.api.wait_for_scan_results(
|
|
431
|
+
task_id=task_id,
|
|
432
|
+
fqdn=pending_device.fqdn,
|
|
433
|
+
platform=pending_device.platform,
|
|
434
|
+
profile=SicuraProfile.LEVEL_1_SERVER,
|
|
435
|
+
)
|
|
436
|
+
else:
|
|
437
|
+
logger.warning(f"Failed to create scan task for device {pending_device.fqdn}")
|
|
438
|
+
# No continue needed here as we're at the end of the loop iteration
|
|
439
|
+
|
|
440
|
+
devices = self.api.get_devices()
|
|
441
|
+
|
|
442
|
+
if not devices:
|
|
443
|
+
logger.warning("No devices found in Sicura")
|
|
444
|
+
return
|
|
445
|
+
|
|
446
|
+
self.num_assets_to_process = len(devices)
|
|
447
|
+
|
|
448
|
+
loading_devices = self.asset_progress.add_task(
|
|
449
|
+
f"[#f8b737]Loading {len(devices)} Sicura devices.",
|
|
450
|
+
total=len(devices),
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
for device in devices:
|
|
454
|
+
# Skip devices without an FQDN
|
|
455
|
+
if not device.fqdn:
|
|
456
|
+
logger.warning(f"Device {device.name} has no FQDN, skipping")
|
|
457
|
+
self.asset_progress.update(loading_devices, advance=1)
|
|
458
|
+
continue
|
|
459
|
+
|
|
460
|
+
# Extract platform as the component name if available
|
|
461
|
+
component_names = []
|
|
462
|
+
if device.platforms:
|
|
463
|
+
component_names.append(device.platforms)
|
|
464
|
+
|
|
465
|
+
# Create an asset from the device information
|
|
466
|
+
yield IntegrationAsset(
|
|
467
|
+
name=device.name,
|
|
468
|
+
identifier=device.fqdn,
|
|
469
|
+
asset_type=AssetType.VM, # Default to server type
|
|
470
|
+
ip_address=device.ip_address,
|
|
471
|
+
fqdn=device.fqdn,
|
|
472
|
+
asset_owner_id=self.assessor_id,
|
|
473
|
+
parent_id=self.plan_id,
|
|
474
|
+
parent_module=regscale_models.SecurityPlan.get_module_slug(),
|
|
475
|
+
asset_category=regscale_models.AssetCategory.Hardware,
|
|
476
|
+
component_names=component_names,
|
|
477
|
+
component_type=regscale_models.ComponentType.Hardware,
|
|
478
|
+
external_id=str(device.id) if device.id else None,
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
self.asset_progress.update(loading_devices, advance=1)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""DuroSuite Variables"""
|
|
4
|
+
|
|
5
|
+
from regscale.core.app.utils.variables import RsVariableType, RsVariablesMeta
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SicuraVariables(metaclass=RsVariablesMeta):
|
|
9
|
+
"""
|
|
10
|
+
Sicura Variables class to define class-level attributes with type annotations and examples
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# Define class-level attributes with type annotations and examples
|
|
14
|
+
sicuraEnabled: RsVariableType(bool, "True", default=False) # type: ignore # noqa: F722,F821
|
|
15
|
+
sicuraURL: RsVariableType(str, "https://sicura.mydomain.com") # type: ignore # noqa: F722,F821
|
|
16
|
+
sicuraToken: RsVariableType(str, "your-sicura-token") # type: ignore # noqa: F722,F821
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Snyk RegScale integration"""
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from os import PathLike
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
|
|
10
|
+
from regscale.models.integration_models.flat_file_importer import FlatFileImporter
|
|
11
|
+
from regscale.models.integration_models.snyk import Snyk
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@click.group()
|
|
15
|
+
def snyk():
|
|
16
|
+
"""Performs actions on Snyk export files."""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@snyk.command(name="import_snyk")
|
|
20
|
+
@FlatFileImporter.common_scanner_options(
|
|
21
|
+
message="File path to the folder containing Snyk .xlsx files to process to RegScale.",
|
|
22
|
+
prompt="File path for Snyk files",
|
|
23
|
+
import_name="snyk",
|
|
24
|
+
)
|
|
25
|
+
def import_snyk(
|
|
26
|
+
folder_path: PathLike[str],
|
|
27
|
+
regscale_ssp_id: int,
|
|
28
|
+
scan_date: datetime,
|
|
29
|
+
mappings_path: PathLike[str],
|
|
30
|
+
disable_mapping: bool,
|
|
31
|
+
s3_bucket: str,
|
|
32
|
+
s3_prefix: str,
|
|
33
|
+
aws_profile: str,
|
|
34
|
+
upload_file: bool,
|
|
35
|
+
):
|
|
36
|
+
"""
|
|
37
|
+
Import scans, vulnerabilities and assets to RegScale from Snyk export files
|
|
38
|
+
"""
|
|
39
|
+
import_synk_files(
|
|
40
|
+
folder_path=folder_path,
|
|
41
|
+
regscale_ssp_id=regscale_ssp_id,
|
|
42
|
+
scan_date=scan_date,
|
|
43
|
+
mappings_path=mappings_path,
|
|
44
|
+
disable_mapping=disable_mapping,
|
|
45
|
+
s3_bucket=s3_bucket,
|
|
46
|
+
s3_prefix=s3_prefix,
|
|
47
|
+
aws_profile=aws_profile,
|
|
48
|
+
upload_file=upload_file,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def import_synk_files(
|
|
53
|
+
folder_path: PathLike[str],
|
|
54
|
+
regscale_ssp_id: int,
|
|
55
|
+
scan_date: datetime,
|
|
56
|
+
mappings_path: PathLike[str],
|
|
57
|
+
disable_mapping: bool,
|
|
58
|
+
s3_bucket: str,
|
|
59
|
+
s3_prefix: str,
|
|
60
|
+
aws_profile: str,
|
|
61
|
+
upload_file: Optional[bool] = True,
|
|
62
|
+
) -> None:
|
|
63
|
+
"""
|
|
64
|
+
Import Snyk scans, vulnerabilities and assets to RegScale from Snyk files
|
|
65
|
+
|
|
66
|
+
:param PathLike[str] folder_path: File path to the folder containing Snyk .xlsx files to process to RegScale
|
|
67
|
+
:param int regscale_ssp_id: The RegScale SSP ID
|
|
68
|
+
:param datetime scan_date: The date of the scan
|
|
69
|
+
:param PathLike[str] mappings_path: The path to the mappings file
|
|
70
|
+
:param bool disable_mapping: Whether to disable custom mappings
|
|
71
|
+
:param str s3_bucket: The S3 bucket to download the files from
|
|
72
|
+
:param str s3_prefix: The S3 prefix to download the files from
|
|
73
|
+
:param str aws_profile: The AWS profile to use for S3 access
|
|
74
|
+
:param Optional[bool] upload_file: Whether to upload the file to RegScale after processing, defaults to True
|
|
75
|
+
:rtype: None
|
|
76
|
+
"""
|
|
77
|
+
FlatFileImporter.import_files(
|
|
78
|
+
import_type=Snyk,
|
|
79
|
+
import_name="Snyk",
|
|
80
|
+
file_types=".xlsx",
|
|
81
|
+
folder_path=folder_path,
|
|
82
|
+
regscale_ssp_id=regscale_ssp_id,
|
|
83
|
+
scan_date=scan_date,
|
|
84
|
+
mappings_path=mappings_path,
|
|
85
|
+
disable_mapping=disable_mapping,
|
|
86
|
+
s3_bucket=s3_bucket,
|
|
87
|
+
s3_prefix=s3_prefix,
|
|
88
|
+
aws_profile=aws_profile,
|
|
89
|
+
upload_file=upload_file,
|
|
90
|
+
)
|