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,332 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""RegScale Gitlab integration"""
|
|
4
|
+
|
|
5
|
+
# standard python imports
|
|
6
|
+
import os
|
|
7
|
+
import re
|
|
8
|
+
import sys
|
|
9
|
+
from urllib.parse import urljoin
|
|
10
|
+
|
|
11
|
+
import click
|
|
12
|
+
import markdown
|
|
13
|
+
import requests
|
|
14
|
+
from rich.progress import Progress
|
|
15
|
+
|
|
16
|
+
from regscale.core.app.internal.login import is_valid
|
|
17
|
+
from regscale.core.app.logz import create_logger
|
|
18
|
+
from regscale.core.app.utils.app_utils import (
|
|
19
|
+
check_license,
|
|
20
|
+
create_progress_object,
|
|
21
|
+
error_and_exit,
|
|
22
|
+
get_current_datetime,
|
|
23
|
+
)
|
|
24
|
+
from regscale.models import regscale_id, regscale_module
|
|
25
|
+
from regscale.models.regscale_models.issue import Issue
|
|
26
|
+
from regscale.models.regscale_models.link import Link
|
|
27
|
+
|
|
28
|
+
job_progress = create_progress_object()
|
|
29
|
+
logger = create_logger()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@click.group()
|
|
33
|
+
def gitlab():
|
|
34
|
+
"""GitLab integration to pull issues via API."""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@gitlab.command(name="sync_issues", help="Integration to GitLab to sync issues into a module.")
|
|
38
|
+
@regscale_id()
|
|
39
|
+
@regscale_module()
|
|
40
|
+
@click.option("--gitlab_url", "-u", default="https://gitlab.com", help="GitLab URL", required=True)
|
|
41
|
+
@click.option(
|
|
42
|
+
"--gitlab_project_id",
|
|
43
|
+
"-gpid",
|
|
44
|
+
required=True,
|
|
45
|
+
help="The ID of the GitLab project to pull issues from.",
|
|
46
|
+
default=os.environ.get("GITLAB_PROJECT"),
|
|
47
|
+
)
|
|
48
|
+
@click.option(
|
|
49
|
+
"--api_token",
|
|
50
|
+
"-t",
|
|
51
|
+
required=True,
|
|
52
|
+
help="Your GitLab API token with API read access.",
|
|
53
|
+
default=os.environ.get("GITLAB_API_TOKEN"),
|
|
54
|
+
)
|
|
55
|
+
@click.option(
|
|
56
|
+
"--include_links",
|
|
57
|
+
"-l",
|
|
58
|
+
is_flag=True,
|
|
59
|
+
help="Include links from the issue description.",
|
|
60
|
+
default=False,
|
|
61
|
+
)
|
|
62
|
+
def sync_issues(
|
|
63
|
+
regscale_id: int,
|
|
64
|
+
regscale_module: str,
|
|
65
|
+
gitlab_url: str,
|
|
66
|
+
gitlab_project_id: int,
|
|
67
|
+
api_token: str,
|
|
68
|
+
include_links: bool,
|
|
69
|
+
):
|
|
70
|
+
"""Sync issues from a GitLab project into a RegScale record."""
|
|
71
|
+
run_sync_issues(
|
|
72
|
+
regscale_id=regscale_id,
|
|
73
|
+
regscale_module=regscale_module,
|
|
74
|
+
gitlab_url=gitlab_url,
|
|
75
|
+
gitlab_project_id=gitlab_project_id,
|
|
76
|
+
api_token=api_token,
|
|
77
|
+
include_links=include_links,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def run_sync_issues(
|
|
82
|
+
regscale_id: int,
|
|
83
|
+
regscale_module: str,
|
|
84
|
+
gitlab_url: str,
|
|
85
|
+
gitlab_project_id: int,
|
|
86
|
+
api_token: str,
|
|
87
|
+
include_links: bool,
|
|
88
|
+
) -> None:
|
|
89
|
+
"""Sync issues from a GitLab project into a module
|
|
90
|
+
|
|
91
|
+
:param int regscale_id: The RegScale ID to sync issues to
|
|
92
|
+
:param str regscale_module: The RegScale module to sync issues to
|
|
93
|
+
:param str gitlab_url: The GitLab URL to sync issues from
|
|
94
|
+
:param int gitlab_project_id: The GitLab project ID to sync issues from
|
|
95
|
+
:param str api_token: The GitLab API token to use
|
|
96
|
+
:param bool include_links: Whether to include links from the issue description
|
|
97
|
+
:rtype: None
|
|
98
|
+
"""
|
|
99
|
+
app = check_license()
|
|
100
|
+
if not is_valid(app=app):
|
|
101
|
+
logger.warn("RegScale token is invalid. please login.")
|
|
102
|
+
sys.exit(1)
|
|
103
|
+
|
|
104
|
+
with job_progress:
|
|
105
|
+
gitlab_issues = get_issues_from_gitlab(gitlab_url, gitlab_project_id, api_token, job_progress)
|
|
106
|
+
|
|
107
|
+
regscale_issues = get_regscale_issues(regscale_id, regscale_module, job_progress)
|
|
108
|
+
logger.debug(f"Fetched {len(regscale_issues)} issues from RegScale.")
|
|
109
|
+
|
|
110
|
+
# Convert the issues to your desired format
|
|
111
|
+
issues = convert_issues(
|
|
112
|
+
gitlab_issues,
|
|
113
|
+
regscale_id,
|
|
114
|
+
regscale_module,
|
|
115
|
+
include_links,
|
|
116
|
+
job_progress,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# # Save or update the converted issues
|
|
120
|
+
save_or_update_issues(issues, regscale_issues, job_progress)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def get_regscale_issues(regscale_id: int, regscale_module: str, job_progress: Progress) -> list:
|
|
124
|
+
"""Function to fetch issues from RegScale
|
|
125
|
+
|
|
126
|
+
:param int regscale_id: The RegScale ID to fetch issues for
|
|
127
|
+
:param str regscale_module: The RegScale module to fetch issues for
|
|
128
|
+
:param Progress job_progress: The progress object to use for updating
|
|
129
|
+
:return: list of regscale issues
|
|
130
|
+
:rtype: list
|
|
131
|
+
"""
|
|
132
|
+
app = check_license()
|
|
133
|
+
task = job_progress.add_task("[#f8b737]Fetching issues from regscale", total=1)
|
|
134
|
+
if regscale_module == "securityplans":
|
|
135
|
+
existing_issues = Issue.fetch_issues_by_ssp(app=app, ssp_id=regscale_id)
|
|
136
|
+
logger.info(f"Fetched {len(existing_issues)} issues from RegScale by SSP.")
|
|
137
|
+
else:
|
|
138
|
+
existing_issues = Issue.fetch_issues_by_parent(
|
|
139
|
+
app=app, regscale_id=regscale_id, regscale_module=regscale_module
|
|
140
|
+
)
|
|
141
|
+
logger.info(f"Fetched {len(existing_issues)} issues from RegScale by issue parent.")
|
|
142
|
+
job_progress.update(task, advance=1)
|
|
143
|
+
return existing_issues
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def save_or_update_issues(gitlab_issues: list, regscale_issues: list, job_progress: Progress) -> None:
|
|
147
|
+
"""Function to save or update issues from GitLab to RegScale
|
|
148
|
+
|
|
149
|
+
:param list gitlab_issues: The list of GitLab issues to save or update
|
|
150
|
+
:param list regscale_issues: The list of RegScale issues to save or update
|
|
151
|
+
:param Progress job_progress: The progress object to use for updating
|
|
152
|
+
:rtype: None
|
|
153
|
+
"""
|
|
154
|
+
app = check_license()
|
|
155
|
+
# figure out which issues need to be updated vs inserted
|
|
156
|
+
task = job_progress.add_task(
|
|
157
|
+
"[#f8b737]Saving issues from GitLab to RegScale...",
|
|
158
|
+
total=len(gitlab_issues),
|
|
159
|
+
)
|
|
160
|
+
regscale_dict = {regscale_issue.dependabotId: regscale_issue for regscale_issue in regscale_issues}
|
|
161
|
+
|
|
162
|
+
for gitlab_issue_obj in gitlab_issues:
|
|
163
|
+
gitlab_issue = gitlab_issue_obj.get("issue")
|
|
164
|
+
# if we have the issue already in the regscale dict, check and update it
|
|
165
|
+
if gitlab_issue.dependabotId in regscale_dict:
|
|
166
|
+
regscale_issue = regscale_dict.get(gitlab_issue.dependabotId)
|
|
167
|
+
# has it updated?
|
|
168
|
+
if regscale_issue.__eq__(gitlab_issue) is False:
|
|
169
|
+
gitlab_issue.id = regscale_issue.id
|
|
170
|
+
try:
|
|
171
|
+
Issue.update_issue(app=app, issue=gitlab_issue)
|
|
172
|
+
logger.info(f"Updated issue {gitlab_issue.id}")
|
|
173
|
+
except Exception as vex:
|
|
174
|
+
logger.error(vex)
|
|
175
|
+
existing_links = Link.fetch_links_by_parent(app, gitlab_issue.id, "issues")
|
|
176
|
+
for link in gitlab_issue_obj.get("links", []):
|
|
177
|
+
# set here for comparison purposes
|
|
178
|
+
link.parentID = gitlab_issue.id
|
|
179
|
+
if link not in existing_links:
|
|
180
|
+
try:
|
|
181
|
+
new_link = Link.insert_link(app=app, link=link)
|
|
182
|
+
logger.info(f"Inserted link {new_link.id}")
|
|
183
|
+
# Add the new link to the existing_links list
|
|
184
|
+
existing_links.append(new_link)
|
|
185
|
+
except Exception as ex:
|
|
186
|
+
logger.error(ex)
|
|
187
|
+
|
|
188
|
+
# insert new issue
|
|
189
|
+
else:
|
|
190
|
+
try:
|
|
191
|
+
issue = Issue.insert_issue(app=app, issue=gitlab_issue)
|
|
192
|
+
if issue is not None and issue.id is not None:
|
|
193
|
+
logger.info(f"Inserted issue {issue.id}")
|
|
194
|
+
except Exception as ex:
|
|
195
|
+
logger.error(ex)
|
|
196
|
+
for link in gitlab_issue_obj.get("links", []):
|
|
197
|
+
link.parentID = issue.id
|
|
198
|
+
try:
|
|
199
|
+
new_link = Link.insert_link(app=app, link=link)
|
|
200
|
+
except Exception as ex:
|
|
201
|
+
logger.error(ex)
|
|
202
|
+
job_progress.update(task, advance=1)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def extract_links_with_labels(text: str, parent_id: int, parent_module: str) -> list[Link]:
|
|
206
|
+
"""Extract links from an issue description text with labels
|
|
207
|
+
|
|
208
|
+
:param str text: The issue description containing links
|
|
209
|
+
:param int parent_id: The parent ID associated with the parent module
|
|
210
|
+
:param str parent_module: The parent module associated with the parent ID
|
|
211
|
+
:return: A list of Link objects extracted from the text
|
|
212
|
+
:rtype: list[Link]
|
|
213
|
+
"""
|
|
214
|
+
results = []
|
|
215
|
+
url_pattern = re.compile(r"https?://(?:[a-zA-Z0-9$@.&+*(),%-]|%[0-9a-fA-F]{2})+")
|
|
216
|
+
|
|
217
|
+
for line in text.split("\n"):
|
|
218
|
+
if ":" in line and ("Link" in line or "link" in line):
|
|
219
|
+
label, url = line.split(":", 1)
|
|
220
|
+
url = url.strip().replace("<br>", "")
|
|
221
|
+
|
|
222
|
+
if url.startswith("https:"):
|
|
223
|
+
url = url[6:].strip()
|
|
224
|
+
|
|
225
|
+
if url_pattern.match(url):
|
|
226
|
+
results.append(
|
|
227
|
+
Link(
|
|
228
|
+
title=label.replace("-", "").strip(),
|
|
229
|
+
url=url,
|
|
230
|
+
parentID=parent_id,
|
|
231
|
+
parentModule=parent_module,
|
|
232
|
+
)
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
return results
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def convert_issues(
|
|
239
|
+
gitlab_issues: list,
|
|
240
|
+
regscale_id: int,
|
|
241
|
+
regscale_module: str,
|
|
242
|
+
include_links: bool,
|
|
243
|
+
job_progress: Progress,
|
|
244
|
+
) -> list:
|
|
245
|
+
"""
|
|
246
|
+
Converts issues from GitLab to regscale
|
|
247
|
+
|
|
248
|
+
:param list gitlab_issues: The list of GitLab issues to convert
|
|
249
|
+
:param int regscale_id: The RegScale ID to convert issues to
|
|
250
|
+
:param str regscale_module: The RegScale module to convert issues to
|
|
251
|
+
:param bool include_links: Whether to include links from the issue description
|
|
252
|
+
:param Progress job_progress: The progress object to use for updating
|
|
253
|
+
:return: list of converted issues
|
|
254
|
+
:rtype: list
|
|
255
|
+
"""
|
|
256
|
+
app = check_license()
|
|
257
|
+
|
|
258
|
+
task = job_progress.add_task("[#f8b737]Converting issues from gitlab...", total=len(gitlab_issues))
|
|
259
|
+
regscale_issues = []
|
|
260
|
+
for issue in gitlab_issues:
|
|
261
|
+
status = "Open"
|
|
262
|
+
if issue.get("state"):
|
|
263
|
+
if issue.get("state") == "open":
|
|
264
|
+
status = "Open"
|
|
265
|
+
elif issue.get("state") == "closed":
|
|
266
|
+
status = "Closed"
|
|
267
|
+
severity_level = Issue.assign_severity(issue.get("weight", 0))
|
|
268
|
+
# Convert the issue to your desired format
|
|
269
|
+
converted_issue = Issue(
|
|
270
|
+
title=issue["title"],
|
|
271
|
+
description=str(markdown.markdown(issue["description"])),
|
|
272
|
+
severityLevel=severity_level,
|
|
273
|
+
issueOwnerId=app.config["userId"],
|
|
274
|
+
costEstimate=0,
|
|
275
|
+
levelOfEffort=0,
|
|
276
|
+
dueDate=issue["due_date"],
|
|
277
|
+
identification="Other",
|
|
278
|
+
dependabotId=str(issue["id"]),
|
|
279
|
+
dateCreated=issue["created_at"],
|
|
280
|
+
parentId=regscale_id,
|
|
281
|
+
parentModule=regscale_module,
|
|
282
|
+
status=status,
|
|
283
|
+
securityPlanId=regscale_id if regscale_module == "securityplans" else None,
|
|
284
|
+
componentId=regscale_id if regscale_module == "components" else None,
|
|
285
|
+
)
|
|
286
|
+
if converted_issue.status == "Closed":
|
|
287
|
+
if issue.get("closed_at"):
|
|
288
|
+
converted_issue.dateCompleted = issue.get("closed_at")
|
|
289
|
+
else:
|
|
290
|
+
converted_issue.dateCompleted = get_current_datetime()
|
|
291
|
+
# Extract the links from the description
|
|
292
|
+
if include_links:
|
|
293
|
+
links = extract_links_with_labels(issue["description"], 0, "issues")
|
|
294
|
+
regscale_issues.append({"issue": converted_issue, "links": links})
|
|
295
|
+
else:
|
|
296
|
+
regscale_issues.append({"issue": converted_issue, "links": []})
|
|
297
|
+
job_progress.update(task, advance=1)
|
|
298
|
+
return regscale_issues
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def get_issues_from_gitlab(gitlab_url: str, gitlab_project_id: int, api_token: str, job_progress: Progress) -> list:
|
|
302
|
+
"""Fetch issues from GitLab
|
|
303
|
+
|
|
304
|
+
:param str gitlab_url: The GitLab URL to fetch issues from
|
|
305
|
+
:param int gitlab_project_id: The GitLab project ID to fetch issues from
|
|
306
|
+
:param str api_token: The GitLab API token to use
|
|
307
|
+
:param Progress job_progress: The progress object to use for updating
|
|
308
|
+
:return: list of issues
|
|
309
|
+
:rtype: list
|
|
310
|
+
"""
|
|
311
|
+
# Define the GitLab API URL for issues
|
|
312
|
+
api_call = f"/api/v4/projects/{gitlab_project_id}/issues"
|
|
313
|
+
url = urljoin(gitlab_url, api_call)
|
|
314
|
+
logger.info("Fetching issues from gitlab...")
|
|
315
|
+
logger.debug(f"Fetching with API token {api_token}")
|
|
316
|
+
# Define the headers, including your API token
|
|
317
|
+
headers = {"Private-Token": api_token}
|
|
318
|
+
# Send a GET request to the API
|
|
319
|
+
fetching_issues = job_progress.add_task("[#f8b737]Fetching issues from gitlab...", total=1)
|
|
320
|
+
response = requests.get(url, headers=headers)
|
|
321
|
+
job_progress.update(fetching_issues, advance=1)
|
|
322
|
+
issues = []
|
|
323
|
+
# If the request was successful
|
|
324
|
+
if response.ok:
|
|
325
|
+
# Load the issues from the response
|
|
326
|
+
issues = response.json()
|
|
327
|
+
logger.info(f"Fetched {len(issues)} issues from gitlab")
|
|
328
|
+
else:
|
|
329
|
+
logger.error(response.status_code)
|
|
330
|
+
logger.error(response.text)
|
|
331
|
+
error_and_exit(f"Failed to get issues from GitLab. Status code: {response.status_code}")
|
|
332
|
+
return issues
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module for processing Grype scan results and loading them into RegScale.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import traceback
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from typing import List, Optional, Union
|
|
9
|
+
|
|
10
|
+
import click
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
from regscale.core.app.utils.file_utils import (
|
|
14
|
+
download_from_s3,
|
|
15
|
+
find_files,
|
|
16
|
+
iterate_files,
|
|
17
|
+
move_file,
|
|
18
|
+
)
|
|
19
|
+
from regscale.models.integration_models.flat_file_importer import FlatFileImporter
|
|
20
|
+
from regscale.models.integration_models.grype_import import GrypeImport
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class GrypeProcessingError(Exception):
|
|
26
|
+
"""Custom exception for Grype processing errors."""
|
|
27
|
+
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@click.group()
|
|
32
|
+
def grype():
|
|
33
|
+
"""Performs actions from the Grype scanner integration."""
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@grype.command("import_scans")
|
|
38
|
+
@FlatFileImporter.common_scanner_options(
|
|
39
|
+
message="File path to the folder containing Grype .json files to process to RegScale.",
|
|
40
|
+
prompt="File path for Grype files",
|
|
41
|
+
import_name="grype",
|
|
42
|
+
)
|
|
43
|
+
@click.option("--destination", "-d", type=click.Path(exists=True, dir_okay=True), required=False)
|
|
44
|
+
@click.option("--file_pattern", "-p", type=str, required=False, default="grype*.json")
|
|
45
|
+
def import_scans(
|
|
46
|
+
destination: Optional[Path],
|
|
47
|
+
file_pattern: str,
|
|
48
|
+
folder_path: Path,
|
|
49
|
+
regscale_ssp_id: int,
|
|
50
|
+
scan_date: datetime,
|
|
51
|
+
mappings_path: Path,
|
|
52
|
+
disable_mapping: bool,
|
|
53
|
+
s3_bucket: str,
|
|
54
|
+
s3_prefix: str,
|
|
55
|
+
aws_profile: str,
|
|
56
|
+
upload_file: bool,
|
|
57
|
+
) -> None:
|
|
58
|
+
"""
|
|
59
|
+
Process Grype scan results from a folder containing Grype scan files and load into RegScale.
|
|
60
|
+
"""
|
|
61
|
+
import_grype_scans(
|
|
62
|
+
destination=destination,
|
|
63
|
+
file_pattern=file_pattern,
|
|
64
|
+
folder_path=folder_path,
|
|
65
|
+
regscale_ssp_id=regscale_ssp_id,
|
|
66
|
+
scan_date=scan_date,
|
|
67
|
+
mappings_path=mappings_path,
|
|
68
|
+
disable_mapping=disable_mapping,
|
|
69
|
+
s3_bucket=s3_bucket,
|
|
70
|
+
s3_prefix=s3_prefix,
|
|
71
|
+
aws_profile=aws_profile,
|
|
72
|
+
upload_file=upload_file,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def import_grype_scans(
|
|
77
|
+
folder_path: Path,
|
|
78
|
+
regscale_ssp_id: int,
|
|
79
|
+
scan_date: datetime,
|
|
80
|
+
mappings_path: Optional[Path] = None,
|
|
81
|
+
disable_mapping: Optional[bool] = False,
|
|
82
|
+
s3_bucket: Optional[str] = None,
|
|
83
|
+
s3_prefix: Optional[str] = None,
|
|
84
|
+
aws_profile: Optional[str] = None,
|
|
85
|
+
destination: Optional[Path] = None,
|
|
86
|
+
file_pattern: Optional[str] = "grype*.json",
|
|
87
|
+
upload_file: Optional[bool] = True,
|
|
88
|
+
) -> None:
|
|
89
|
+
"""
|
|
90
|
+
Process Grype scan results from a folder container grype scan files and load into RegScale.
|
|
91
|
+
|
|
92
|
+
:param Path folder_path: Path to the Grype scan results JSON file
|
|
93
|
+
:param int regscale_ssp_id: RegScale SSP ID
|
|
94
|
+
:param datetime scan_date: The date of the scan
|
|
95
|
+
:param Optional[Path] mappings_path: Path to the header mapping file, default: None
|
|
96
|
+
:param Optional[bool] disable_mapping: Disable the header mapping, default: False
|
|
97
|
+
:param Optional[str] s3_bucket: S3 bucket to download scan files from, default: None
|
|
98
|
+
:param Optional[str] s3_prefix: Prefix (folder path) within the S3 bucket, default: None
|
|
99
|
+
:param Optional[str] aws_profile: AWS profile to use for S3 access, default: None
|
|
100
|
+
:param Optional[Path] destination: Destination folder for processed files, default: None
|
|
101
|
+
:param Optional[str] file_pattern: File pattern to search for in the directory, default: grype*.json
|
|
102
|
+
:param Optional[bool] upload_file: Whether to upload the file to RegScale after processing, default: True
|
|
103
|
+
:raises GrypeProcessingError: If there is an error processing the Grype results
|
|
104
|
+
:rtype: None
|
|
105
|
+
"""
|
|
106
|
+
from regscale.exceptions import ValidationException
|
|
107
|
+
from regscale.core.app.application import Application
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
if s3_bucket and s3_prefix and aws_profile:
|
|
111
|
+
download_from_s3(bucket=s3_bucket, prefix=s3_prefix, local_path=destination, aws_profile=aws_profile)
|
|
112
|
+
files = find_files(path=destination, pattern=file_pattern)
|
|
113
|
+
logger.info("Downloaded all Grype scan files from S3. Processing...")
|
|
114
|
+
elif destination and not s3_bucket:
|
|
115
|
+
logger.info("Moving Grype scan files to %s", destination)
|
|
116
|
+
stored_file_collection = find_files(path=folder_path, pattern=file_pattern)
|
|
117
|
+
move_all_files(stored_file_collection, destination)
|
|
118
|
+
files = find_files(path=destination, pattern=file_pattern)
|
|
119
|
+
logger.info("Done moving files")
|
|
120
|
+
else:
|
|
121
|
+
stored_file_collection = find_files(path=folder_path, pattern=file_pattern)
|
|
122
|
+
files = stored_file_collection
|
|
123
|
+
if not files:
|
|
124
|
+
logger.error("No Grype scan results found in the specified directory")
|
|
125
|
+
return
|
|
126
|
+
|
|
127
|
+
except Exception as e:
|
|
128
|
+
logger.error(f"Error processing Grype results: {str(e)}")
|
|
129
|
+
logger.error(traceback.format_exc())
|
|
130
|
+
raise GrypeProcessingError(f"Failed to process Grype results: {str(e)}")
|
|
131
|
+
|
|
132
|
+
for file in files:
|
|
133
|
+
try:
|
|
134
|
+
GrypeImport(
|
|
135
|
+
name="Grype",
|
|
136
|
+
app=Application(),
|
|
137
|
+
file_path=str(file),
|
|
138
|
+
file_type=file.suffix,
|
|
139
|
+
parent_id=regscale_ssp_id,
|
|
140
|
+
parent_module="securityplans",
|
|
141
|
+
scan_date=scan_date,
|
|
142
|
+
mappings_path=mappings_path,
|
|
143
|
+
disable_mapping=disable_mapping,
|
|
144
|
+
upload_file=upload_file,
|
|
145
|
+
file_name=file.name,
|
|
146
|
+
)
|
|
147
|
+
except ValidationException as e:
|
|
148
|
+
logger.error(f"Validation error on {file}: {e}")
|
|
149
|
+
continue
|
|
150
|
+
logger.info("Completed Grype processing.")
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def move_all_files(file_collection: List[Union[Path, str]], destination: Union[Path, str]) -> None:
|
|
154
|
+
"""
|
|
155
|
+
Move all Grype files in the current directory to a folder called 'processed'.
|
|
156
|
+
|
|
157
|
+
:param List[Union[Path, str]] file_collection: A list of file paths or S3 URIs
|
|
158
|
+
:param Union[Path, str] destination: The destination folder
|
|
159
|
+
:rtype: None
|
|
160
|
+
"""
|
|
161
|
+
for file in iterate_files(file_collection):
|
|
162
|
+
file_path = Path(file)
|
|
163
|
+
new_filename = f"{file_path.stem}{file_path.suffix}"
|
|
164
|
+
new_file_path = Path(destination) / new_filename
|
|
165
|
+
move_file(file, new_file_path)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""IBM AppScan 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.ibm import AppScan
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@click.group()
|
|
15
|
+
def ibm():
|
|
16
|
+
"""Performs actions on IBM AppScan files."""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@ibm.command(name="import_appscan")
|
|
20
|
+
@FlatFileImporter.common_scanner_options(
|
|
21
|
+
message="File path to the folder containing IBM AppScan .csv files to process to RegScale.",
|
|
22
|
+
prompt="File path for IBM AppScan files",
|
|
23
|
+
import_name="ibm_appscan",
|
|
24
|
+
)
|
|
25
|
+
def import_appscan(
|
|
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
|
+
) -> None:
|
|
36
|
+
"""
|
|
37
|
+
Import IBM AppScan scans, vulnerabilities and assets to RegScale from IBM AppScan files
|
|
38
|
+
"""
|
|
39
|
+
import_appscan_files(
|
|
40
|
+
folder_path,
|
|
41
|
+
regscale_ssp_id,
|
|
42
|
+
scan_date,
|
|
43
|
+
mappings_path,
|
|
44
|
+
disable_mapping,
|
|
45
|
+
s3_bucket,
|
|
46
|
+
s3_prefix,
|
|
47
|
+
aws_profile,
|
|
48
|
+
upload_file,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def import_appscan_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 IBM AppScan scans, vulnerabilities and assets to RegScale from IBM AppScan files
|
|
65
|
+
|
|
66
|
+
:param PathLike[str] folder_path: File path to the folder containing IBM AppScan .csv 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=AppScan,
|
|
79
|
+
import_name="IBM AppScan",
|
|
80
|
+
file_types=".csv",
|
|
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
|
+
)
|
|
File without changes
|