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,406 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Test the Application class used by the RegScale CLI.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from unittest.mock import patch, MagicMock
|
|
7
|
+
|
|
8
|
+
from requests import Response
|
|
9
|
+
|
|
10
|
+
from regscale.core.app.application import Application
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TestApplication:
|
|
14
|
+
test_config_file = "test_application_config.yaml"
|
|
15
|
+
os.environ["REGSCALE_CONFIG_FILE"] = test_config_file
|
|
16
|
+
app = Application()
|
|
17
|
+
app.config_file = test_config_file
|
|
18
|
+
test_domain = "https://example.com"
|
|
19
|
+
test_token = "Bearer test_token"
|
|
20
|
+
|
|
21
|
+
def teardown_method(self, method):
|
|
22
|
+
"""
|
|
23
|
+
Remove the test config file after each test
|
|
24
|
+
"""
|
|
25
|
+
if os.path.exists(self.test_config_file):
|
|
26
|
+
os.remove(self.test_config_file)
|
|
27
|
+
|
|
28
|
+
def test_init(self):
|
|
29
|
+
assert isinstance(self.app, Application)
|
|
30
|
+
assert isinstance(self.app, Application)
|
|
31
|
+
assert self.app.config != {}
|
|
32
|
+
assert self.app.local_config is True
|
|
33
|
+
assert self.app.running_in_airflow is False
|
|
34
|
+
|
|
35
|
+
def test_singleton(self):
|
|
36
|
+
test_config = {"key": "value"}
|
|
37
|
+
app2 = Application()
|
|
38
|
+
assert self.app == app2
|
|
39
|
+
app3 = Application(config=test_config)
|
|
40
|
+
assert test_config["key"] == app3["key"]
|
|
41
|
+
assert app3 != self.app
|
|
42
|
+
assert app3 != app2
|
|
43
|
+
|
|
44
|
+
@patch("regscale.core.app.internal.login.parse_user_id_from_jwt")
|
|
45
|
+
@patch("requests.get")
|
|
46
|
+
def test_fetch_config_from_regscale_success(self, mock_get, mock_parse_user_id):
|
|
47
|
+
mock_parse_user_id.return_value = "test_user_id"
|
|
48
|
+
mock_response = MagicMock()
|
|
49
|
+
mock_response.json.return_value = {"cliConfig": "key: value"}
|
|
50
|
+
mock_get.return_value = mock_response
|
|
51
|
+
config = self.app._fetch_config_from_regscale(config=self.app.config)
|
|
52
|
+
assert "domain" in config
|
|
53
|
+
assert config["userId"] == "test_user_id"
|
|
54
|
+
assert config["key"] == "value"
|
|
55
|
+
|
|
56
|
+
@patch("regscale.core.app.internal.login.parse_user_id_from_jwt")
|
|
57
|
+
@patch("requests.get")
|
|
58
|
+
def test_fetch_config_from_regscale_success_with_envars(self, mock_get, mock_parse_user_id):
|
|
59
|
+
mock_parse_user_id.return_value = "test_user_id"
|
|
60
|
+
mock_response = MagicMock()
|
|
61
|
+
mock_response.json.return_value = {"cliConfig": "key: value"}
|
|
62
|
+
mock_get.return_value = mock_response
|
|
63
|
+
os.environ["REGSCALE_DOMAIN"] = self.test_domain
|
|
64
|
+
os.environ["REGSCALE_TOKEN"] = self.test_token
|
|
65
|
+
config = self.app._fetch_config_from_regscale(config={})
|
|
66
|
+
assert config["domain"] == self.test_domain
|
|
67
|
+
assert config["token"] == self.test_token
|
|
68
|
+
assert config["userId"] == "test_user_id"
|
|
69
|
+
assert config["key"] == "value"
|
|
70
|
+
|
|
71
|
+
@patch("requests.get")
|
|
72
|
+
def test_fetch_config_from_regscale_failure(self, mock_get):
|
|
73
|
+
mock_response = MagicMock()
|
|
74
|
+
mock_response.json.return_value = "Not found."
|
|
75
|
+
mock_response.status_code = 404
|
|
76
|
+
mock_get.return_value = mock_response
|
|
77
|
+
os.environ["REGSCALE_DOMAIN"] = self.test_domain
|
|
78
|
+
os.environ["REGSCALE_TOKEN"] = self.test_token
|
|
79
|
+
empty_config = self.app._fetch_config_from_regscale()
|
|
80
|
+
assert empty_config == {}
|
|
81
|
+
with patch.object(self.app.logger, "error") as mock_logger_error:
|
|
82
|
+
config = self.app._fetch_config_from_regscale(config=self.app.config)
|
|
83
|
+
mock_logger_error.assert_called_once()
|
|
84
|
+
assert config == {}
|
|
85
|
+
|
|
86
|
+
def test_gen_config(self):
|
|
87
|
+
self.app.local_config = True
|
|
88
|
+
self.app.config_file = "test_gen_config.yaml"
|
|
89
|
+
config = self.app._gen_config()
|
|
90
|
+
assert "key" not in config
|
|
91
|
+
assert "domain" in config
|
|
92
|
+
assert "token" in config
|
|
93
|
+
|
|
94
|
+
small_config = {"key": "value", "domain": self.test_domain}
|
|
95
|
+
config = self.app._gen_config(small_config)
|
|
96
|
+
assert config["key"] == "value"
|
|
97
|
+
assert config["domain"] == self.test_domain
|
|
98
|
+
os.remove(self.app.config_file)
|
|
99
|
+
|
|
100
|
+
def test_gen_config_airflow(self):
|
|
101
|
+
self.app.running_in_airflow = True
|
|
102
|
+
with patch.object(self.app, "_get_airflow_config", return_value={"key": "value"}):
|
|
103
|
+
config = self.app._gen_config()
|
|
104
|
+
assert config == {"key": "value"}
|
|
105
|
+
|
|
106
|
+
def test_gen_config_with_provided_config(self):
|
|
107
|
+
self.app.local_config = True
|
|
108
|
+
config = {"key": "value"}
|
|
109
|
+
with patch.object(self.app, "_get_env", return_value={"env_key": "env_value"}):
|
|
110
|
+
with patch.object(self.app, "verify_config", return_value={"key": "value", "env_key": "env_value"}):
|
|
111
|
+
with patch.object(self.app, "save_config") as mock_save_config:
|
|
112
|
+
result = self.app._gen_config(config)
|
|
113
|
+
assert result == {"key": "value", "env_key": "env_value"}
|
|
114
|
+
mock_save_config.assert_called_once()
|
|
115
|
+
|
|
116
|
+
def test_gen_config_without_local_config(self):
|
|
117
|
+
self.app.local_config = False
|
|
118
|
+
with patch.object(self.app, "_get_env", return_value={"env_key": "env_value"}):
|
|
119
|
+
with patch.object(self.app, "verify_config", return_value={"env_key": "env_value"}):
|
|
120
|
+
with patch.object(self.app, "save_config") as mock_save_config:
|
|
121
|
+
result = self.app._gen_config()
|
|
122
|
+
assert result == {"env_key": "env_value"}
|
|
123
|
+
mock_save_config.assert_called_once()
|
|
124
|
+
|
|
125
|
+
def test_gen_config_with_file_config(self):
|
|
126
|
+
self.app.local_config = True
|
|
127
|
+
with patch.object(self.app, "_get_conf", return_value={"file_key": "file_value"}):
|
|
128
|
+
with patch.object(self.app, "_get_env", return_value={"env_key": "env_value"}):
|
|
129
|
+
with patch.object(
|
|
130
|
+
self.app, "verify_config", return_value={"file_key": "file_value", "env_key": "env_value"}
|
|
131
|
+
):
|
|
132
|
+
with patch.object(self.app, "save_config") as mock_save_config:
|
|
133
|
+
result = self.app._gen_config()
|
|
134
|
+
assert result == {"file_key": "file_value", "env_key": "env_value"}
|
|
135
|
+
mock_save_config.assert_called_once()
|
|
136
|
+
|
|
137
|
+
def test_gen_config_scanner_error(self):
|
|
138
|
+
from yaml.scanner import ScannerError
|
|
139
|
+
|
|
140
|
+
self.app.local_config = True
|
|
141
|
+
with patch.object(self.app, "_get_conf", side_effect=ScannerError):
|
|
142
|
+
with patch.object(self.app, "save_config") as mock_save_config:
|
|
143
|
+
result = self.app._gen_config()
|
|
144
|
+
assert result == self.app.template
|
|
145
|
+
# called twice because the first call is to save the default config
|
|
146
|
+
mock_save_config.assert_called_once()
|
|
147
|
+
|
|
148
|
+
def test_get_airflow_config_with_dict(self):
|
|
149
|
+
config = {"key": "value"}
|
|
150
|
+
with patch.object(self.app, "_fetch_config_from_regscale", return_value={"key": "value"}):
|
|
151
|
+
result = self.app._get_airflow_config(config)
|
|
152
|
+
assert result == {"key": "value"}
|
|
153
|
+
|
|
154
|
+
def test_get_airflow_config_with_str(self):
|
|
155
|
+
config = "{'key': 'value'}"
|
|
156
|
+
with patch.object(self.app, "_fetch_config_from_regscale", return_value={"key": "value"}):
|
|
157
|
+
result = self.app._get_airflow_config(config)
|
|
158
|
+
assert result == {"key": "value"}
|
|
159
|
+
|
|
160
|
+
def test_get_airflow_config_with_env_vars(self):
|
|
161
|
+
os.environ["REGSCALE_TOKEN"] = self.test_token
|
|
162
|
+
os.environ["REGSCALE_DOMAIN"] = self.test_domain
|
|
163
|
+
with patch.object(self.app, "_fetch_config_from_regscale", return_value={"key": "value"}):
|
|
164
|
+
result = self.app._get_airflow_config()
|
|
165
|
+
assert result == {"key": "value"}
|
|
166
|
+
|
|
167
|
+
def test_get_airflow_config_no_config(self):
|
|
168
|
+
os.environ["REGSCALE_TOKEN"] = ""
|
|
169
|
+
os.environ["REGSCALE_DOMAIN"] = ""
|
|
170
|
+
result = self.app._get_airflow_config()
|
|
171
|
+
assert result is None
|
|
172
|
+
|
|
173
|
+
os.environ["REGSCALE_TOKEN"] = self.test_token
|
|
174
|
+
os.environ["REGSCALE_DOMAIN"] = self.test_domain
|
|
175
|
+
with patch.object(
|
|
176
|
+
self.app, "_fetch_config_from_regscale", return_value={"token": self.test_token, "domain": self.test_domain}
|
|
177
|
+
):
|
|
178
|
+
result = self.app._get_airflow_config()
|
|
179
|
+
assert result["token"] == self.test_token
|
|
180
|
+
assert result["domain"] == self.test_domain
|
|
181
|
+
|
|
182
|
+
def test_get_airflow_config_invalid_json(self):
|
|
183
|
+
config = "{'key': 'value'"
|
|
184
|
+
with patch.object(self.app.logger, "debug") as mock_logger_debug:
|
|
185
|
+
result = self.app._get_airflow_config(config)
|
|
186
|
+
assert result is None
|
|
187
|
+
mock_logger_debug.assert_called()
|
|
188
|
+
|
|
189
|
+
def test_get_env_with_matching_keys(self):
|
|
190
|
+
with patch.object(self.app, "template", {"key1": "value1", "key2": "value2"}):
|
|
191
|
+
with patch.dict(os.environ, {"key1": "env_value1", "key2": "env_value2"}):
|
|
192
|
+
result = self.app._get_env()
|
|
193
|
+
assert result == {"key1": "env_value1", "key2": "env_value2"}
|
|
194
|
+
|
|
195
|
+
def test_get_env_with_no_matching_keys(self):
|
|
196
|
+
with patch.object(self.app, "template", {"key1": "value1", "key2": "value2"}):
|
|
197
|
+
with patch.dict(os.environ, {"key3": "env_value3"}):
|
|
198
|
+
result = self.app._get_env()
|
|
199
|
+
assert result == {"key1": "value1", "key2": "value2"}
|
|
200
|
+
|
|
201
|
+
def test_get_env_with_key_error(self):
|
|
202
|
+
with patch.object(self.app, "template", {"key1": "value1", "key2": "value2"}):
|
|
203
|
+
with patch.dict(os.environ, {"key1": "env_value1"}):
|
|
204
|
+
with patch.object(self.app.logger, "error") as mock_logger_error:
|
|
205
|
+
result = self.app._get_env()
|
|
206
|
+
assert result == {"key1": "env_value1", "key2": "value2"}
|
|
207
|
+
mock_logger_error.assert_not_called()
|
|
208
|
+
|
|
209
|
+
def test_get_env_with_template_match(self):
|
|
210
|
+
with patch.object(self.app, "template", {"key1": "value1", "key2": "value2"}):
|
|
211
|
+
with patch.dict(os.environ, {"key1": "value1", "key2": "value2"}):
|
|
212
|
+
result = self.app._get_env()
|
|
213
|
+
assert result == {"key1": "value1", "key2": "value2"}
|
|
214
|
+
assert self.app.templated is True
|
|
215
|
+
|
|
216
|
+
def test_get_env_without_template_match(self):
|
|
217
|
+
with patch.object(self.app, "template", {"key1": "value1", "key2": "value2"}):
|
|
218
|
+
with patch.dict(os.environ, {"key1": "env_value1"}):
|
|
219
|
+
result = self.app._get_env()
|
|
220
|
+
assert result == {"key1": "env_value1", "key2": "value2"}
|
|
221
|
+
assert self.app.templated is False
|
|
222
|
+
|
|
223
|
+
def test_get_conf(self):
|
|
224
|
+
self.app.config_file = self.test_config_file
|
|
225
|
+
self.app = Application(config={"key": "value"})
|
|
226
|
+
with patch("yaml.safe_load", return_value={"key": "value"}):
|
|
227
|
+
config = self.app._get_conf()
|
|
228
|
+
assert config == {"key": "value"}
|
|
229
|
+
with patch("yaml.safe_load", side_effect=FileNotFoundError):
|
|
230
|
+
config = self.app._get_conf()
|
|
231
|
+
assert config is None
|
|
232
|
+
|
|
233
|
+
def test_save_config(self):
|
|
234
|
+
from regscale.core.app.utils.api_handler import APIHandler
|
|
235
|
+
|
|
236
|
+
self.app.config_file = "test_save_config.yaml"
|
|
237
|
+
test_config = {"key": "value"}
|
|
238
|
+
with patch.object(self.app, "running_in_airflow", True):
|
|
239
|
+
self.app.save_config(test_config)
|
|
240
|
+
config = self.app.load_config()
|
|
241
|
+
assert "key" not in config
|
|
242
|
+
|
|
243
|
+
self.app.running_in_airflow = False
|
|
244
|
+
self.app.save_config(test_config)
|
|
245
|
+
config = self.app.load_config()
|
|
246
|
+
assert config is not None
|
|
247
|
+
assert config["key"] == "value"
|
|
248
|
+
assert "domain" not in config
|
|
249
|
+
|
|
250
|
+
test_api_handler = APIHandler()
|
|
251
|
+
self.app.api_handler = test_api_handler
|
|
252
|
+
test_config = {"api_handler": "testing_api_handler", "domain": self.test_domain}
|
|
253
|
+
self.app.save_config(test_config)
|
|
254
|
+
config = self.app.load_config()
|
|
255
|
+
assert config["api_handler"] == "testing_api_handler"
|
|
256
|
+
assert test_api_handler.domain == self.test_domain
|
|
257
|
+
assert test_api_handler.config == test_config
|
|
258
|
+
|
|
259
|
+
with patch.object(self.app.logger, "error") as mock_logger_error:
|
|
260
|
+
with patch("yaml.dump", side_effect=OSError):
|
|
261
|
+
self.app.save_config({})
|
|
262
|
+
mock_logger_error.assert_called_once()
|
|
263
|
+
|
|
264
|
+
os.remove(self.app.config_file)
|
|
265
|
+
|
|
266
|
+
def test_get_regscale_license(self):
|
|
267
|
+
with patch("requests.get"):
|
|
268
|
+
regscale_license = self.app.get_regscale_license(MagicMock())
|
|
269
|
+
assert isinstance(regscale_license, MagicMock)
|
|
270
|
+
|
|
271
|
+
def test_load_config(self):
|
|
272
|
+
self.app.config_file = self.test_config_file
|
|
273
|
+
with patch("yaml.safe_load", side_effect=FileNotFoundError):
|
|
274
|
+
config = self.app.load_config()
|
|
275
|
+
assert config == {}
|
|
276
|
+
|
|
277
|
+
self.app.save_config({"key": "value"})
|
|
278
|
+
config = self.app.load_config()
|
|
279
|
+
assert config == {"key": "value"}
|
|
280
|
+
|
|
281
|
+
def test_get_regscale_license_with_config(self):
|
|
282
|
+
api = MagicMock()
|
|
283
|
+
api.config = {"domain": self.test_domain}
|
|
284
|
+
api.get.return_value = Response()
|
|
285
|
+
self.app.config = api.config
|
|
286
|
+
|
|
287
|
+
with patch.object(self.app, "retrieve_domain", return_value=self.test_domain):
|
|
288
|
+
response = self.app.get_regscale_license(api)
|
|
289
|
+
api.get.assert_called_once_with(url="https://example.com/api/config/getlicense")
|
|
290
|
+
assert isinstance(response, Response)
|
|
291
|
+
|
|
292
|
+
def test_get_regscale_license_without_config(self):
|
|
293
|
+
api = MagicMock()
|
|
294
|
+
api.config = {"domain": self.test_domain}
|
|
295
|
+
api.get.return_value = Response()
|
|
296
|
+
self.app.config = None
|
|
297
|
+
|
|
298
|
+
with patch.object(self.app, "_gen_config", return_value={"domain": self.test_domain}):
|
|
299
|
+
with patch.object(self.app, "retrieve_domain", return_value=self.test_domain):
|
|
300
|
+
response = self.app.get_regscale_license(api)
|
|
301
|
+
api.get.assert_called_once_with(url="https://example.com/api/config/getlicense")
|
|
302
|
+
assert isinstance(response, Response)
|
|
303
|
+
|
|
304
|
+
def test_get_regscale_license_with_airflow_config(self):
|
|
305
|
+
api = MagicMock()
|
|
306
|
+
api.config = None
|
|
307
|
+
api.get.return_value = Response()
|
|
308
|
+
self.app.config = None
|
|
309
|
+
self.app.running_in_airflow = True
|
|
310
|
+
|
|
311
|
+
with patch.object(self.app, "_get_airflow_config", return_value={"domain": self.test_domain}):
|
|
312
|
+
with patch.object(self.app, "retrieve_domain", return_value=self.test_domain):
|
|
313
|
+
response = self.app.get_regscale_license(api)
|
|
314
|
+
api.get.assert_called_once_with(url="https://example.com/api/config/getlicense")
|
|
315
|
+
assert isinstance(response, Response)
|
|
316
|
+
|
|
317
|
+
def test_get_regscale_license_with_suppressed_exception(self):
|
|
318
|
+
import requests
|
|
319
|
+
|
|
320
|
+
api = MagicMock()
|
|
321
|
+
api.config = {"domain": self.test_domain}
|
|
322
|
+
api.get.side_effect = requests.RequestException
|
|
323
|
+
self.app.config = {"domain": self.test_domain}
|
|
324
|
+
|
|
325
|
+
with patch.object(self.app, "retrieve_domain", return_value=self.test_domain):
|
|
326
|
+
response = self.app.get_regscale_license(api)
|
|
327
|
+
api.get.assert_called_once_with(url="https://example.com/api/config/getlicense")
|
|
328
|
+
assert response is None
|
|
329
|
+
|
|
330
|
+
def test_retrieve_domain(self):
|
|
331
|
+
possible_envars = ["REGSCALE_DOMAIN", "PLATFORM_HOST", "domain"]
|
|
332
|
+
for envar in possible_envars:
|
|
333
|
+
with patch("os.environ", {envar: self.test_domain}):
|
|
334
|
+
domain = self.app.retrieve_domain()
|
|
335
|
+
assert domain == self.test_domain
|
|
336
|
+
with patch("os.environ", {envar: "www.example.com"}):
|
|
337
|
+
domain = self.app.retrieve_domain()
|
|
338
|
+
assert domain == self.app.template["domain"]
|
|
339
|
+
|
|
340
|
+
def test_verify_config(self):
|
|
341
|
+
template = {"key": "value"}
|
|
342
|
+
config = {"key": "other_value"}
|
|
343
|
+
updated_config = self.app.verify_config(template, config)
|
|
344
|
+
assert updated_config == {"key": "other_value"}
|
|
345
|
+
|
|
346
|
+
def test_verify_config_with_missing_keys(self):
|
|
347
|
+
template = {"key1": "value1", "key2": "value2"}
|
|
348
|
+
config = {"key1": "value1"}
|
|
349
|
+
expected_config = {"key1": "value1", "key2": "value2"}
|
|
350
|
+
updated_config = self.app.verify_config(template, config)
|
|
351
|
+
assert updated_config == expected_config
|
|
352
|
+
|
|
353
|
+
def test_verify_config_with_type_mismatch(self):
|
|
354
|
+
template = {"key1": "value1", "key2": 2}
|
|
355
|
+
config = {"key1": "value1", "key2": "wrong_type"}
|
|
356
|
+
expected_config = {"key1": "value1", "key2": 2}
|
|
357
|
+
updated_config = self.app.verify_config(template, config)
|
|
358
|
+
assert updated_config == expected_config
|
|
359
|
+
|
|
360
|
+
def test_verify_config_with_nested_dict(self):
|
|
361
|
+
template = {"key1": "value1", "key2": {"subkey1": "subvalue1"}}
|
|
362
|
+
config = {"key1": "value1", "key2": {"subkey1": "wrong_value"}}
|
|
363
|
+
expected_config = {"key1": "value1", "key2": {"subkey1": "wrong_value"}}
|
|
364
|
+
updated_config = self.app.verify_config(template, config)
|
|
365
|
+
assert updated_config == expected_config
|
|
366
|
+
|
|
367
|
+
def test_verify_config_with_additional_keys(self):
|
|
368
|
+
template = {"key1": "value1"}
|
|
369
|
+
config = {"key1": "value1", "key2": "value2"}
|
|
370
|
+
expected_config = {"key1": "value1", "key2": "value2"}
|
|
371
|
+
updated_config = self.app.verify_config(template, config)
|
|
372
|
+
assert updated_config == expected_config
|
|
373
|
+
|
|
374
|
+
def test_verify_config_with_empty_config(self):
|
|
375
|
+
template = {"key1": "value1", "key2": "value2"}
|
|
376
|
+
config = {}
|
|
377
|
+
expected_config = {"key1": "value1", "key2": "value2"}
|
|
378
|
+
updated_config = self.app.verify_config(template, config)
|
|
379
|
+
assert updated_config == expected_config
|
|
380
|
+
|
|
381
|
+
def test_getitem(self):
|
|
382
|
+
self.app.config = {"key": "value"}
|
|
383
|
+
assert self.app["key"] == "value"
|
|
384
|
+
|
|
385
|
+
def test_setitem(self):
|
|
386
|
+
self.app.config = {}
|
|
387
|
+
self.app["key"] = "value"
|
|
388
|
+
assert self.app.config == {"key": "value"}
|
|
389
|
+
|
|
390
|
+
def test_delitem(self):
|
|
391
|
+
self.app.config = {"key": "value"}
|
|
392
|
+
del self.app["key"]
|
|
393
|
+
assert self.app.config == {}
|
|
394
|
+
|
|
395
|
+
def test_iter(self):
|
|
396
|
+
self.app.config = {"key1": "value1", "key2": "value2"}
|
|
397
|
+
assert list(self.app) == ["key1", "key2"]
|
|
398
|
+
|
|
399
|
+
def test_len(self):
|
|
400
|
+
self.app.config = {"key1": "value1", "key2": "value2"}
|
|
401
|
+
assert len(self.app) == 2
|
|
402
|
+
|
|
403
|
+
def test_contains(self):
|
|
404
|
+
self.app.config = {"key": "value"}
|
|
405
|
+
assert "key" in self.app
|
|
406
|
+
assert "nonexistent_key" not in self.app
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Test the login module."""
|
|
2
|
+
|
|
3
|
+
from unittest.mock import patch
|
|
4
|
+
|
|
5
|
+
from regscale.core.login import get_regscale_token
|
|
6
|
+
from regscale.core.app.api import Api
|
|
7
|
+
from regscale.core.app.application import Application
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@patch("regscale.core.login.Api.post")
|
|
11
|
+
@patch.dict("os.environ", {"REGSCALE_DOMAIN": "example_value"})
|
|
12
|
+
def test_get_regscale_token(mock_post):
|
|
13
|
+
api = Api()
|
|
14
|
+
mock_response = mock_post.return_value
|
|
15
|
+
mock_response.status_code = 200
|
|
16
|
+
mock_response.json.return_value = {
|
|
17
|
+
"id": "example_id",
|
|
18
|
+
"auth_token": "example_token",
|
|
19
|
+
}
|
|
20
|
+
result = get_regscale_token(api=api, username="example_user", password="example_password")
|
|
21
|
+
result2 = get_regscale_token(
|
|
22
|
+
api=api,
|
|
23
|
+
username="example_user",
|
|
24
|
+
password="example_password",
|
|
25
|
+
domain="example2_domain",
|
|
26
|
+
)
|
|
27
|
+
result3 = get_regscale_token(
|
|
28
|
+
api=api,
|
|
29
|
+
username="example_user",
|
|
30
|
+
password="example_password",
|
|
31
|
+
domain="example3_domain",
|
|
32
|
+
mfa_token="123456",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
assert result == ("example_id", "example_token")
|
|
36
|
+
assert result2 == ("example_id", "example_token")
|
|
37
|
+
assert result3 == ("example_id", "example_token")
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from unittest import mock
|
|
4
|
+
from rich.logging import RichHandler
|
|
5
|
+
from regscale.core.app.logz import create_logger
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_create_logger_creates_logger_with_default_settings():
|
|
9
|
+
logger = create_logger()
|
|
10
|
+
assert logger.name == "regscale"
|
|
11
|
+
assert logger.level == logging.INFO
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_create_logger_respects_propagate_parameter():
|
|
15
|
+
logger = create_logger(propagate=True)
|
|
16
|
+
assert logger.propagate is True
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_create_logger_adds_custom_handler():
|
|
20
|
+
custom_handler = logging.StreamHandler()
|
|
21
|
+
logger = create_logger(custom_handler=custom_handler)
|
|
22
|
+
assert any(isinstance(handler, logging.StreamHandler) for handler in logger.handlers)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_create_logger_creates_file_handler_when_not_in_container():
|
|
26
|
+
with mock.patch.dict(os.environ, {"REGSCALE_ECS": "False"}):
|
|
27
|
+
logger = create_logger()
|
|
28
|
+
assert any(isinstance(handler, logging.handlers.TimedRotatingFileHandler) for handler in logger.handlers)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_create_logger_does_not_create_file_handler_when_in_container():
|
|
32
|
+
with mock.patch.dict(os.environ, {"REGSCALE_ECS": "True"}):
|
|
33
|
+
logger = create_logger()
|
|
34
|
+
assert not any(isinstance(handler, logging.handlers.TimedRotatingFileHandler) for handler in logger.handlers)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_create_logger_uses_custom_log_level():
|
|
38
|
+
with mock.patch.dict(os.environ, {"LOGLEVEL": "DEBUG"}):
|
|
39
|
+
logger = create_logger()
|
|
40
|
+
assert logger.level == logging.DEBUG
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_create_logger_uses_custom_log_width():
|
|
44
|
+
with mock.patch.dict(os.environ, {"REGSCALE_LOG_WIDTH": "100"}):
|
|
45
|
+
logger = create_logger()
|
|
46
|
+
assert any(
|
|
47
|
+
getattr(handler.console, "width", None) == 100
|
|
48
|
+
for handler in logger.handlers
|
|
49
|
+
if isinstance(handler, RichHandler)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_create_logger_handles_invalid_log_width():
|
|
54
|
+
with mock.patch.dict(os.environ, {"REGSCALE_LOG_WIDTH": "invalid"}):
|
|
55
|
+
logger = create_logger()
|
|
56
|
+
assert any(
|
|
57
|
+
getattr(handler.console, "width", None) is not None
|
|
58
|
+
for handler in logger.handlers
|
|
59
|
+
if isinstance(handler, RichHandler)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_getting_regscale_logger():
|
|
64
|
+
logger = logging.getLogger("regscale")
|
|
65
|
+
assert logger.name == "regscale"
|
|
66
|
+
assert len(logger.handlers) > 0
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from unittest.mock import Mock
|
|
3
|
+
|
|
4
|
+
from regscale.models.integration_models.sbom.cyclone_dx import CycloneDXJsonGenerator
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_initialization():
|
|
8
|
+
device = {"deviceName": "test-device", "manufacturer": "Test Corp"}
|
|
9
|
+
generator = CycloneDXJsonGenerator(device)
|
|
10
|
+
|
|
11
|
+
assert generator.device == device
|
|
12
|
+
assert isinstance(generator.logger, logging.Logger)
|
|
13
|
+
assert generator.device_info.name == "test-device"
|
|
14
|
+
assert generator.device_info.manufacturer == "Test Corp"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_initialization_custom_logger():
|
|
18
|
+
logger = Mock()
|
|
19
|
+
generator = CycloneDXJsonGenerator({}, logger)
|
|
20
|
+
assert generator.logger == logger
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_device_description_generation():
|
|
24
|
+
device = {"manufacturer": "Test Corp", "model": "Model X", "deviceType": "Router"}
|
|
25
|
+
generator = CycloneDXJsonGenerator(device)
|
|
26
|
+
description = generator.generate_device_description()
|
|
27
|
+
assert description == "Test Corp Model X Router"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_device_description_partial_info():
|
|
31
|
+
device = {"model": "Model X"}
|
|
32
|
+
generator = CycloneDXJsonGenerator(device)
|
|
33
|
+
description = generator.generate_device_description()
|
|
34
|
+
assert description == "Model X"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_device_description_empty():
|
|
38
|
+
generator = CycloneDXJsonGenerator({})
|
|
39
|
+
description = generator.generate_device_description()
|
|
40
|
+
assert description == "Unknown Device"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_component_validation():
|
|
44
|
+
generator = CycloneDXJsonGenerator({})
|
|
45
|
+
valid_component = {"type": "library", "name": "test-lib"}
|
|
46
|
+
invalid_type = {"type": "invalid", "name": "test"}
|
|
47
|
+
missing_field = {"type": "library"}
|
|
48
|
+
|
|
49
|
+
assert generator.validate(valid_component)
|
|
50
|
+
assert not generator.validate(invalid_type)
|
|
51
|
+
assert not generator.validate(missing_field)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_generate_sbom():
|
|
55
|
+
device = {"deviceName": "test-device", "manufacturer": "Test Corp", "easDeviceId": "device-123"}
|
|
56
|
+
components = [{"type": "library", "name": "lib1"}, {"type": "framework", "name": "framework1"}]
|
|
57
|
+
|
|
58
|
+
generator = CycloneDXJsonGenerator(device)
|
|
59
|
+
sbom = generator.generate_sbom(components)
|
|
60
|
+
|
|
61
|
+
assert sbom["bomFormat"] == "CycloneDX"
|
|
62
|
+
assert sbom["specVersion"] == "1.4"
|
|
63
|
+
assert len(sbom["components"]) == 3 # device + 2 components
|
|
64
|
+
assert len(sbom["dependencies"]) == 1
|
|
65
|
+
assert sbom["dependencies"][0]["ref"] == "device-123"
|
|
66
|
+
assert len(sbom["dependencies"][0]["dependsOn"]) == 2
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_generate_sbom_invalid_components():
|
|
70
|
+
device = {"deviceName": "test-device"}
|
|
71
|
+
components = [
|
|
72
|
+
{"type": "library", "name": "lib1"},
|
|
73
|
+
{"type": "invalid", "name": "invalid1"},
|
|
74
|
+
{"name": "missing-type"},
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
generator = CycloneDXJsonGenerator(device)
|
|
78
|
+
sbom = generator.generate_sbom(components)
|
|
79
|
+
|
|
80
|
+
assert len(sbom["components"]) == 2 # device + 1 valid component
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_sbom_metadata():
|
|
84
|
+
generator = CycloneDXJsonGenerator({})
|
|
85
|
+
sbom = generator.generate_sbom([])
|
|
86
|
+
|
|
87
|
+
assert sbom["metadata"]["tools"][0]["name"] == "RegScale CLI"
|