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
tests/fixtures/models.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from typing import List, Type, TypeVar
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from unittest.mock import patch
|
|
5
|
+
from regscale.models.regscale_models.regscale_model import RegScaleModel
|
|
6
|
+
from regscale.models import regscale_models
|
|
7
|
+
|
|
8
|
+
T = TypeVar("T", bound=RegScaleModel)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.fixture
|
|
12
|
+
def mock_regscale_models(mock_api_handler):
|
|
13
|
+
"""
|
|
14
|
+
Fixture to patch various methods for RegScaleModel and its subclasses to use model cache and avoid API calls.
|
|
15
|
+
|
|
16
|
+
:param mock_api_handler: Mocked API handler
|
|
17
|
+
:yield: None
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def mock_get_all_by_parent(cls: Type[T], parent_id: int, *args, **kwargs) -> List[T]:
|
|
21
|
+
"""
|
|
22
|
+
Mock method to get all objects by parent ID.
|
|
23
|
+
|
|
24
|
+
:param Type[T] cls: The class of the objects to retrieve
|
|
25
|
+
:param int parent_id: The ID of the parent object
|
|
26
|
+
:return: List of objects matching the parent ID and other criteria
|
|
27
|
+
"""
|
|
28
|
+
parent_module = kwargs.get("parent_module")
|
|
29
|
+
|
|
30
|
+
return [
|
|
31
|
+
obj
|
|
32
|
+
for obj in cls._object_cache.values()
|
|
33
|
+
if isinstance(obj, cls)
|
|
34
|
+
and parent_id == getattr(obj, cls._parent_id_field)
|
|
35
|
+
and (not parent_module or obj.parentModule == parent_module)
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
def mock_issue_find_by_other_identifier(other_identifier: str) -> List[regscale_models.Issue]:
|
|
39
|
+
"""
|
|
40
|
+
Mock method to find issues by other identifier.
|
|
41
|
+
|
|
42
|
+
:param str other_identifier: The other identifier to search for
|
|
43
|
+
:return: List of Issue objects matching the other identifier
|
|
44
|
+
"""
|
|
45
|
+
return [
|
|
46
|
+
issue
|
|
47
|
+
for issue in regscale_models.Issue._object_cache.values()
|
|
48
|
+
if isinstance(issue, regscale_models.Issue) and issue.otherIdentifier == other_identifier
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
def mock_vulnerability_mapping_find_by_issue(
|
|
52
|
+
issue_id: int, status: str = "all"
|
|
53
|
+
) -> List[regscale_models.VulnerabilityMapping]:
|
|
54
|
+
"""
|
|
55
|
+
Mock method to find vulnerability mappings by issue ID and status.
|
|
56
|
+
|
|
57
|
+
:param int issue_id: The ID of the issue to search for
|
|
58
|
+
:param str status: The status of the vulnerability mapping (default: "all")
|
|
59
|
+
:return: List of VulnerabilityMapping objects matching the criteria
|
|
60
|
+
"""
|
|
61
|
+
return [
|
|
62
|
+
mapping
|
|
63
|
+
for mapping in regscale_models.VulnerabilityMapping._object_cache.values()
|
|
64
|
+
if isinstance(mapping, regscale_models.VulnerabilityMapping)
|
|
65
|
+
and (status == "all" or mapping.status.lower() == status.lower())
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
def mock_get_object(cls: Type[T], object_id: int) -> T:
|
|
69
|
+
"""
|
|
70
|
+
Mock method to get an object by its ID.
|
|
71
|
+
|
|
72
|
+
:param Type[T] cls: The class of the object to retrieve
|
|
73
|
+
:param int object_id: The ID of the object to retrieve
|
|
74
|
+
:return: The object if found, None otherwise
|
|
75
|
+
"""
|
|
76
|
+
# Try to get the object from the cache first
|
|
77
|
+
cached_object = next((obj for obj in cls._object_cache.values() if obj.id == object_id), None)
|
|
78
|
+
if cached_object:
|
|
79
|
+
return cached_object
|
|
80
|
+
|
|
81
|
+
# If not in cache, simulate an API call (you might want to raise an exception here instead)
|
|
82
|
+
return None
|
|
83
|
+
|
|
84
|
+
with patch.object(RegScaleModel, "get_all_by_parent", classmethod(mock_get_all_by_parent)), patch.object(
|
|
85
|
+
regscale_models.Issue, "find_by_other_identifier", mock_issue_find_by_other_identifier
|
|
86
|
+
), patch.object(
|
|
87
|
+
regscale_models.VulnerabilityMapping, "find_by_issue", mock_vulnerability_mapping_find_by_issue
|
|
88
|
+
), patch.object(
|
|
89
|
+
RegScaleModel, "get_object", classmethod(mock_get_object)
|
|
90
|
+
):
|
|
91
|
+
yield
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""Test fixture class used during CLI testing"""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
import random
|
|
6
|
+
import sys
|
|
7
|
+
import uuid
|
|
8
|
+
from logging import Logger
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Optional, Union
|
|
11
|
+
|
|
12
|
+
import pytest
|
|
13
|
+
import yaml
|
|
14
|
+
|
|
15
|
+
from regscale.core.app.api import Api
|
|
16
|
+
from regscale.core.app.application import Application
|
|
17
|
+
from regscale.core.app.internal.login import login
|
|
18
|
+
from tests.conftest_utils import INIT_CONF_PYTEST
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class CLITestFixture:
|
|
22
|
+
"""
|
|
23
|
+
Test fixture for the CLI application
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
app: Application
|
|
27
|
+
api: Api
|
|
28
|
+
config: dict
|
|
29
|
+
logger: Logger
|
|
30
|
+
title_prefix: str
|
|
31
|
+
|
|
32
|
+
def update_config_with_env(self):
|
|
33
|
+
"""
|
|
34
|
+
Update the Application.config values with the corresponding env values if both conditions are met:
|
|
35
|
+
- the config value is the same as the template
|
|
36
|
+
- the env value is not empty
|
|
37
|
+
"""
|
|
38
|
+
key_env = {
|
|
39
|
+
"domain": "REGSCALE_DOMAIN",
|
|
40
|
+
"token": "REGSCALE_TOKEN",
|
|
41
|
+
"jiraUrl": "JIRA_URL",
|
|
42
|
+
"jiraUserName": "JIRA_USERNAME",
|
|
43
|
+
"jiraApiToken": "JIRA_API_TOKEN",
|
|
44
|
+
"wizClientId": "WIZCLIENTID",
|
|
45
|
+
"wizClientSecret": "WIZCLIENTSECRET",
|
|
46
|
+
"snowUrl": "SNOW_URL",
|
|
47
|
+
"snowUserName": "SNOW_USERNAME",
|
|
48
|
+
"snowPassword": "SNOW_PASSWORD",
|
|
49
|
+
"sicuraUrl": "SICURA_URL",
|
|
50
|
+
"sicuraToken": "SICURA_TOKEN",
|
|
51
|
+
"nistCpeApiKey": "NIST_CPE_API_KEY",
|
|
52
|
+
"qualysUserName": "QUALYS_USERNAME",
|
|
53
|
+
"qualysPassword": "QUALYS_PASSWORD",
|
|
54
|
+
"qualysUrl": "QUALYS_URL",
|
|
55
|
+
}
|
|
56
|
+
for key, env in key_env.items():
|
|
57
|
+
config_value = self.app.config.get(key, "")
|
|
58
|
+
template_value = self.app.template.get(key, "")
|
|
59
|
+
env_value = os.getenv(env, "")
|
|
60
|
+
self.app.config[key] = env_value if config_value == template_value and env_value else config_value
|
|
61
|
+
|
|
62
|
+
hard_coded_test_values = {
|
|
63
|
+
"gcpScanType": "organization",
|
|
64
|
+
"gcpOrganizationId": "000000000000",
|
|
65
|
+
"timeout": 360,
|
|
66
|
+
}
|
|
67
|
+
for key, value in hard_coded_test_values.items():
|
|
68
|
+
self.app.config[key] = value
|
|
69
|
+
|
|
70
|
+
def verify_config(self, config_key: Union[str, list[str]], compare_template: bool = True) -> None:
|
|
71
|
+
"""
|
|
72
|
+
Verify the configuration values and compare them to the template
|
|
73
|
+
|
|
74
|
+
:param Union[str, list[str]] config_key: Configuration key or list of keys to verify
|
|
75
|
+
:param bool compare_template: Whether to compare the configuration values to the template, defaults to True
|
|
76
|
+
:rtype: None
|
|
77
|
+
"""
|
|
78
|
+
if isinstance(config_key, list):
|
|
79
|
+
for key in config_key:
|
|
80
|
+
self.verify_config(key, compare_template)
|
|
81
|
+
else:
|
|
82
|
+
assert self.app.config.get(config_key) is not None
|
|
83
|
+
if compare_template:
|
|
84
|
+
assert self.app.config.get(config_key) != self.app.template.get(config_key)
|
|
85
|
+
|
|
86
|
+
@staticmethod
|
|
87
|
+
def get_tests_dir(suffix: Optional[Union[str, Path]] = None) -> Path:
|
|
88
|
+
"""
|
|
89
|
+
Get the current working directory
|
|
90
|
+
|
|
91
|
+
:param Optional[Union[str, Path]] suffix: The suffix to append to the path, defaults to None
|
|
92
|
+
:return: Path of the responses directory with a trailing slash
|
|
93
|
+
:rtype: Path
|
|
94
|
+
"""
|
|
95
|
+
cur_dir = Path(os.getcwd())
|
|
96
|
+
if cur_dir.stem.lower() in ["commercial", "internal", "public"]:
|
|
97
|
+
# get the repo root
|
|
98
|
+
# EX: regscale-cli/tests/regscale/integrations/INTEGRATIONTYPE/test_name.py
|
|
99
|
+
cwd = cur_dir.parent.parent.parent.parent
|
|
100
|
+
elif cur_dir.stem.lower() == "tests":
|
|
101
|
+
cwd = Path("../")
|
|
102
|
+
else:
|
|
103
|
+
cwd = Path(os.getcwd())
|
|
104
|
+
return cwd / suffix if suffix else cwd
|
|
105
|
+
|
|
106
|
+
@pytest.fixture(autouse=True)
|
|
107
|
+
def cli_test_fixture(self, request):
|
|
108
|
+
"""
|
|
109
|
+
Test fixture for the CLI application
|
|
110
|
+
|
|
111
|
+
:param request: Pytest request object
|
|
112
|
+
:return: RegScale CLI Application object
|
|
113
|
+
:rtype: Application
|
|
114
|
+
"""
|
|
115
|
+
logger = logging.getLogger(__name__)
|
|
116
|
+
logger.info("Test Setup")
|
|
117
|
+
|
|
118
|
+
# Application is already set up, so we just need to update the config with the environment variables
|
|
119
|
+
self.app = Application()
|
|
120
|
+
self.app.local_config = False
|
|
121
|
+
self.update_config_with_env()
|
|
122
|
+
# Convert the INIT_CONF_PYTEST string into a dictionary
|
|
123
|
+
config_dict = yaml.safe_load(INIT_CONF_PYTEST)
|
|
124
|
+
test_config = {**config_dict, **self.app.config}
|
|
125
|
+
self.app.save_config(test_config)
|
|
126
|
+
self.config = self.app.config
|
|
127
|
+
python_info = f"Python{sys.version_info.major}.{sys.version_info.minor}"
|
|
128
|
+
random_id = uuid.uuid3(uuid.NAMESPACE_DNS, python_info)
|
|
129
|
+
self.title_prefix = f"{python_info} Test {random_id} - "
|
|
130
|
+
# login with token if available
|
|
131
|
+
if token := os.getenv("REGSCALE_TOKEN") or self.config.get("token"):
|
|
132
|
+
login(token=token, app=self.app)
|
|
133
|
+
elif "REGSCALE_USERNAME" in os.environ and "REGSCALE_PASSWORD" in os.environ:
|
|
134
|
+
login(
|
|
135
|
+
str_user=os.getenv("REGSCALE_USERNAME"),
|
|
136
|
+
str_password=os.getenv("REGSCALE_PASSWORD"),
|
|
137
|
+
app=self.app,
|
|
138
|
+
)
|
|
139
|
+
self.api = Api()
|
|
140
|
+
self.logger = logger
|
|
141
|
+
|
|
142
|
+
logger.info(f"Test Setup Complete: {self.title_prefix}")
|
|
143
|
+
# Test Execution
|
|
144
|
+
yield self.app
|
tests/mocks/__init__.py
ADDED
|
File without changes
|
tests/mocks/objects.py
ADDED
tests/mocks/response.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Create mocked requests.Response objects."""
|
|
2
|
+
|
|
3
|
+
from unittest.mock import Mock
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def create_mock_response(
|
|
9
|
+
status_code=200,
|
|
10
|
+
json_data=None,
|
|
11
|
+
text_data=None,
|
|
12
|
+
headers=None,
|
|
13
|
+
ok=True,
|
|
14
|
+
):
|
|
15
|
+
"""
|
|
16
|
+
Generate a custom requests.Response object using unittest.mock.
|
|
17
|
+
|
|
18
|
+
:status_code (int, optional): The HTTP status code for the response.
|
|
19
|
+
:json_data (dict, optional): The JSON data to be returned by the response's json() method.
|
|
20
|
+
:text_data (str, optional): The text data to be returned by the response's text attribute.
|
|
21
|
+
:headers (dict, optional): The headers for the response.
|
|
22
|
+
:ok (bool, optional): The response.ok value.
|
|
23
|
+
|
|
24
|
+
:returns Mock: A unittest.mock.Mock instance with the specified attributes and behavior.
|
|
25
|
+
"""
|
|
26
|
+
mock_response = Mock(spec=requests.Response)
|
|
27
|
+
mock_response.status_code = status_code
|
|
28
|
+
mock_response.json.return_value = json_data
|
|
29
|
+
mock_response.text = text_data
|
|
30
|
+
mock_response.headers = headers or {}
|
|
31
|
+
mock_response.ok = ok
|
|
32
|
+
return mock_response
|
tests/mocks/xml.py
ADDED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Tests for the Api class"""
|
|
4
|
+
import os
|
|
5
|
+
from unittest.mock import MagicMock, patch
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from regscale.core.app.api import Api, normalize_url
|
|
10
|
+
from regscale.core.app.application import Application
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.fixture
|
|
14
|
+
def mock_config():
|
|
15
|
+
"""Fixture for mocking config"""
|
|
16
|
+
return {
|
|
17
|
+
"token": "test-token",
|
|
18
|
+
"domain": "https://api.example.com",
|
|
19
|
+
"maxThreads": 10,
|
|
20
|
+
"ssl_verify": True,
|
|
21
|
+
"timeout": 10,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.fixture
|
|
26
|
+
def api(mock_config):
|
|
27
|
+
"""Fixture for creating an Api instance with mocked config"""
|
|
28
|
+
with patch("regscale.core.app.application.Application") as mock_app:
|
|
29
|
+
mock_app.return_value.config = mock_config
|
|
30
|
+
api = Api()
|
|
31
|
+
api.session = MagicMock()
|
|
32
|
+
return api
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_handle_headers_with_no_merge(api):
|
|
36
|
+
"""Test _handle_headers when merge_headers is False"""
|
|
37
|
+
custom_headers = {"Custom-Header": "value"}
|
|
38
|
+
result = api._handle_headers(custom_headers, merge_headers=False)
|
|
39
|
+
assert result == custom_headers
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_handle_headers_with_merge(api):
|
|
43
|
+
"""Test _handle_headers when merge_headers is True"""
|
|
44
|
+
custom_headers = {"Custom-Header": "value"}
|
|
45
|
+
result = api._handle_headers(custom_headers, merge_headers=True)
|
|
46
|
+
|
|
47
|
+
assert result["Custom-Header"] == "value"
|
|
48
|
+
assert result["accept"] == api.accept
|
|
49
|
+
assert result["Content-Type"] == api.content_type
|
|
50
|
+
assert result["Authorization"] == "test-token"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_handle_headers_with_no_headers(api):
|
|
54
|
+
"""Test _handle_headers when headers is None"""
|
|
55
|
+
# When merge_headers is False, should return empty dict for None headers
|
|
56
|
+
result = api._handle_headers(None, merge_headers=False)
|
|
57
|
+
assert result["accept"] == api.accept
|
|
58
|
+
assert result["Content-Type"] == api.content_type
|
|
59
|
+
assert result["Authorization"] == "test-token"
|
|
60
|
+
|
|
61
|
+
# When merge_headers is True, should return default headers
|
|
62
|
+
result = api._handle_headers(None, merge_headers=True)
|
|
63
|
+
assert result["accept"] == api.accept
|
|
64
|
+
assert result["Content-Type"] == api.content_type
|
|
65
|
+
assert result["Authorization"] == "test-token"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_handle_headers_with_empty_headers(api):
|
|
69
|
+
"""Test _handle_headers when headers is an empty dict"""
|
|
70
|
+
result = api._handle_headers({}, merge_headers=True)
|
|
71
|
+
|
|
72
|
+
assert len(result) == 3
|
|
73
|
+
assert result["accept"] == api.accept
|
|
74
|
+
assert result["Content-Type"] == api.content_type
|
|
75
|
+
assert result["Authorization"] == "test-token"
|
|
76
|
+
|
|
77
|
+
# Test with merge_headers=False
|
|
78
|
+
result = api._handle_headers({}, merge_headers=False)
|
|
79
|
+
assert result == {}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def test_get_request_success(api):
|
|
83
|
+
"""Test successful GET request"""
|
|
84
|
+
mock_response = MagicMock()
|
|
85
|
+
mock_response.status_code = 200
|
|
86
|
+
mock_response.text = '{"data": "test"}'
|
|
87
|
+
api.session.get.return_value = mock_response
|
|
88
|
+
|
|
89
|
+
response = api.get("https://api.example.com/test")
|
|
90
|
+
|
|
91
|
+
assert response.status_code == 200
|
|
92
|
+
assert response.text == '{"data": "test"}'
|
|
93
|
+
api.session.get.assert_called_once()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def test_post_request_success(api):
|
|
97
|
+
"""Test successful POST request"""
|
|
98
|
+
mock_response = MagicMock()
|
|
99
|
+
mock_response.status_code = 200
|
|
100
|
+
mock_response.text = '{"data": "created"}'
|
|
101
|
+
api.session.post.return_value = mock_response
|
|
102
|
+
|
|
103
|
+
json_data = {"key": "value"}
|
|
104
|
+
response = api.post("https://api.example.com/test", json=json_data)
|
|
105
|
+
|
|
106
|
+
assert response.status_code == 200
|
|
107
|
+
assert response.text == '{"data": "created"}'
|
|
108
|
+
api.session.post.assert_called_once()
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def test_put_request_success(api):
|
|
112
|
+
"""Test successful PUT request"""
|
|
113
|
+
mock_response = MagicMock()
|
|
114
|
+
mock_response.status_code = 200
|
|
115
|
+
mock_response.text = '{"data": "updated"}'
|
|
116
|
+
api.session.put.return_value = mock_response
|
|
117
|
+
|
|
118
|
+
json_data = {"key": "value"}
|
|
119
|
+
response = api.put("https://api.example.com/test", json=json_data)
|
|
120
|
+
|
|
121
|
+
assert response.status_code == 200
|
|
122
|
+
assert response.text == '{"data": "updated"}'
|
|
123
|
+
api.session.put.assert_called_once()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def test_delete_request_success(api):
|
|
127
|
+
"""Test successful DELETE request"""
|
|
128
|
+
mock_response = MagicMock()
|
|
129
|
+
mock_response.status_code = 200
|
|
130
|
+
mock_response.text = '{"data": "deleted"}'
|
|
131
|
+
api.session.delete.return_value = mock_response
|
|
132
|
+
|
|
133
|
+
response = api.delete("https://api.example.com/test")
|
|
134
|
+
|
|
135
|
+
assert response.status_code == 200
|
|
136
|
+
assert response.text == '{"data": "deleted"}'
|
|
137
|
+
api.session.delete.assert_called_once()
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def test_request_with_401_retry(api):
|
|
141
|
+
"""Test request handling 401 unauthorized with retry"""
|
|
142
|
+
mock_response_401 = MagicMock()
|
|
143
|
+
mock_response_401.status_code = 401
|
|
144
|
+
|
|
145
|
+
mock_response_200 = MagicMock()
|
|
146
|
+
mock_response_200.status_code = 200
|
|
147
|
+
mock_response_200.text = '{"data": "success"}'
|
|
148
|
+
|
|
149
|
+
api.session.get.side_effect = [mock_response_401, mock_response_200]
|
|
150
|
+
|
|
151
|
+
with patch.object(api, "_handle_401", return_value=True):
|
|
152
|
+
response = api.get("https://api.example.com/test")
|
|
153
|
+
|
|
154
|
+
assert response.status_code == 200
|
|
155
|
+
assert response.text == '{"data": "success"}'
|
|
156
|
+
assert api.session.get.call_count == 2
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def test_normalize_url():
|
|
160
|
+
"""Test URL normalization"""
|
|
161
|
+
test_cases = [
|
|
162
|
+
("http://example.com//api//v1/", "http://example.com/api/v1"),
|
|
163
|
+
("example.com/api/v1", "http://example.com/api/v1"),
|
|
164
|
+
("https://example.com/api//v1", "https://example.com/api/v1"),
|
|
165
|
+
("http://example.com/api/v1/", "http://example.com/api/v1"),
|
|
166
|
+
]
|
|
167
|
+
|
|
168
|
+
for input_url, expected_url in test_cases:
|
|
169
|
+
assert normalize_url(input_url) == expected_url
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def test_graph_query_success(api):
|
|
173
|
+
"""Test successful GraphQL query"""
|
|
174
|
+
mock_response = MagicMock()
|
|
175
|
+
mock_response.status_code = 200
|
|
176
|
+
mock_response.json.return_value = {
|
|
177
|
+
"data": {"vulnerabilities": {"items": [{"id": 1}], "pageInfo": {"hasNextPage": False}}}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
api.session.post.return_value = mock_response
|
|
181
|
+
query = """
|
|
182
|
+
query {
|
|
183
|
+
vulnerabilities {
|
|
184
|
+
items {
|
|
185
|
+
id
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
"""
|
|
190
|
+
result = api.graph(query)
|
|
191
|
+
|
|
192
|
+
assert "vulnerabilities" in result
|
|
193
|
+
assert isinstance(result["vulnerabilities"]["items"], list)
|
|
194
|
+
assert result["vulnerabilities"]["items"][0]["id"] == 1
|
|
195
|
+
api.session.post.assert_called_once()
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def test_ssl_verify_false_envar():
|
|
199
|
+
"""Test that SSL verification setting is passed to the session via envar"""
|
|
200
|
+
with patch.dict(os.environ, {"sslVerify": "false"}):
|
|
201
|
+
assert os.getenv("sslVerify") == "false"
|
|
202
|
+
api = Api()
|
|
203
|
+
assert api.session.verify is False
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def test_ssl_verify_true_envar():
|
|
207
|
+
"""Test that SSL verification setting is passed to the session via envar"""
|
|
208
|
+
with patch.dict(os.environ, {"sslVerify": "true"}):
|
|
209
|
+
assert os.getenv("sslVerify") == "true"
|
|
210
|
+
api = Api()
|
|
211
|
+
assert api.verify is True
|
|
212
|
+
assert api.session.verify is True
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def test_ssl_verify_false_config():
|
|
216
|
+
"""Test that SSL verification setting is passed to the session via init.yaml"""
|
|
217
|
+
app = Application(config={"sslVerify": False})
|
|
218
|
+
app.config_file = "test_ssl_verify_false_config.yaml"
|
|
219
|
+
app.save_config(app.config)
|
|
220
|
+
assert app.config["sslVerify"] is False
|
|
221
|
+
api = Api()
|
|
222
|
+
assert api.verify is False
|
|
223
|
+
assert api.session.verify is False
|
|
224
|
+
# os.remove(app.config_file)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def test_ssl_verify_true_config():
|
|
228
|
+
"""Test that SSL verification setting is passed to the session init.yaml"""
|
|
229
|
+
app = Application(config={"sslVerify": True})
|
|
230
|
+
assert app.config["sslVerify"] is True
|
|
231
|
+
api = Api()
|
|
232
|
+
assert api.session.verify is True
|