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,413 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""Click BaseModels."""
|
|
4
|
+
|
|
5
|
+
import contextlib
|
|
6
|
+
import inspect
|
|
7
|
+
from typing import Any, List, Optional, Union, Callable, Tuple, Dict
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
import click.core
|
|
11
|
+
from pydantic import BaseModel, ConfigDict, field_validator
|
|
12
|
+
|
|
13
|
+
from regscale.models.inspect_models import SignatureModel
|
|
14
|
+
from regscale.core.lazy_group import LazyGroup
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ClickOption(BaseModel):
|
|
18
|
+
"""A BaseModel based on a click object
|
|
19
|
+
This is the simplest unit in the click hierarchy, representing an option that can be passed to a command.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
model_config = ConfigDict(extra="ignore", arbitrary_types_allowed=True)
|
|
23
|
+
|
|
24
|
+
name: str
|
|
25
|
+
value: Any = None
|
|
26
|
+
default: Any = None
|
|
27
|
+
option: Optional[Union[click.core.Option, dict]] = None
|
|
28
|
+
type: Optional[str] = None
|
|
29
|
+
help: Optional[str] = None
|
|
30
|
+
prompt: Optional[str] = None
|
|
31
|
+
confirmation_prompt: Optional[bool] = None
|
|
32
|
+
is_flag: Optional[bool] = None
|
|
33
|
+
is_bool_flag: Optional[bool] = None
|
|
34
|
+
count: Optional[int] = None
|
|
35
|
+
allow_from_autoenv: Optional[bool] = None
|
|
36
|
+
expose_value: Optional[bool] = None
|
|
37
|
+
is_eager: Optional[bool] = None
|
|
38
|
+
callback: Optional[Union[str, Any]] = None
|
|
39
|
+
callback_signature: Optional[Any] = None
|
|
40
|
+
|
|
41
|
+
@field_validator("option")
|
|
42
|
+
def _check_option(cls, var: Any) -> Any:
|
|
43
|
+
"""
|
|
44
|
+
Check if option is a click.Option or dict
|
|
45
|
+
|
|
46
|
+
:param Any var: The option to check
|
|
47
|
+
:return: The option
|
|
48
|
+
:rtype: Any
|
|
49
|
+
"""
|
|
50
|
+
if not isinstance(var, (dict, click.core.Option)):
|
|
51
|
+
raise TypeError("option must be a click.Option or dict")
|
|
52
|
+
return var
|
|
53
|
+
|
|
54
|
+
@classmethod
|
|
55
|
+
def from_option(
|
|
56
|
+
cls,
|
|
57
|
+
option: click.core.Option,
|
|
58
|
+
include_callback: bool = True,
|
|
59
|
+
include_option: bool = False,
|
|
60
|
+
) -> "ClickOption":
|
|
61
|
+
"""
|
|
62
|
+
Build a ClickOption class from a click.Option
|
|
63
|
+
|
|
64
|
+
:param click.core.Option option: The click.Option to convert
|
|
65
|
+
:param bool include_callback: Whether to include the callback, defaults to True
|
|
66
|
+
:param bool include_option: Whether to include the option, defaults to False
|
|
67
|
+
:return: A ClickOption object
|
|
68
|
+
:rtype: ClickOption
|
|
69
|
+
"""
|
|
70
|
+
data = {
|
|
71
|
+
"option": option if include_option else option.__dict__,
|
|
72
|
+
"help": option.help,
|
|
73
|
+
"name": option.name,
|
|
74
|
+
"default": option.default,
|
|
75
|
+
"type": str(option.type),
|
|
76
|
+
"prompt": option.prompt,
|
|
77
|
+
"confirmation_prompt": option.confirmation_prompt,
|
|
78
|
+
"is_flag": option.is_flag,
|
|
79
|
+
"is_bool_flag": option.is_bool_flag,
|
|
80
|
+
"count": option.count,
|
|
81
|
+
"allow_from_autoenv": option.allow_from_autoenv,
|
|
82
|
+
"expose_value": option.expose_value,
|
|
83
|
+
"is_eager": option.is_eager,
|
|
84
|
+
"callback": (option.callback if include_callback else option.callback.__qualname__),
|
|
85
|
+
}
|
|
86
|
+
# get the signature of the callback,
|
|
87
|
+
if option.callback is not None:
|
|
88
|
+
sig = inspect.signature(option.callback)
|
|
89
|
+
data["callback_signature"] = {
|
|
90
|
+
"parameters": [
|
|
91
|
+
{
|
|
92
|
+
"name": name,
|
|
93
|
+
"default": (param.default if param.default is not inspect.Parameter.empty else None),
|
|
94
|
+
"kind": param.kind,
|
|
95
|
+
"annotation": (param.annotation if param.annotation is not inspect.Parameter.empty else None),
|
|
96
|
+
}
|
|
97
|
+
for name, param in sig.parameters.items()
|
|
98
|
+
],
|
|
99
|
+
"return_annotation": (
|
|
100
|
+
sig.return_annotation if sig.return_annotation is not inspect.Signature.empty else None
|
|
101
|
+
),
|
|
102
|
+
}
|
|
103
|
+
return cls(**data)
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def required(self) -> bool:
|
|
107
|
+
"""
|
|
108
|
+
Make sure it is a required parameter.
|
|
109
|
+
|
|
110
|
+
:return: True if required, False otherwise
|
|
111
|
+
:rtype: bool
|
|
112
|
+
"""
|
|
113
|
+
return self.prompt is False and self.default is None
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class ClickCommand(BaseModel):
|
|
117
|
+
model_config = ConfigDict(extra="ignore", arbitrary_types_allowed=True)
|
|
118
|
+
|
|
119
|
+
name: str
|
|
120
|
+
command: Optional[click.core.Command] = None
|
|
121
|
+
help: Optional[str] = None
|
|
122
|
+
options_metavar: Optional[str] = None
|
|
123
|
+
context_settings: Optional[Any] = None
|
|
124
|
+
params: Dict[str, ClickOption]
|
|
125
|
+
callback: Optional[Union[str, Any]] = None
|
|
126
|
+
signatures: Optional[SignatureModel] = None
|
|
127
|
+
|
|
128
|
+
@field_validator("command")
|
|
129
|
+
def _check_command(cls, var: Any) -> Any:
|
|
130
|
+
"""
|
|
131
|
+
Validate a click.Command
|
|
132
|
+
|
|
133
|
+
:param Any var: The command to validate
|
|
134
|
+
:return: The command
|
|
135
|
+
:rtype: Any
|
|
136
|
+
"""
|
|
137
|
+
if var is None:
|
|
138
|
+
return var
|
|
139
|
+
if not isinstance(var, (click.Command, click.core.Command)):
|
|
140
|
+
print(f"command must be a click.Command not {type(var)}")
|
|
141
|
+
return var
|
|
142
|
+
|
|
143
|
+
@classmethod
|
|
144
|
+
def from_command(
|
|
145
|
+
cls,
|
|
146
|
+
command: click.core.Command,
|
|
147
|
+
include_callback: bool = True,
|
|
148
|
+
include_command: bool = False,
|
|
149
|
+
) -> "ClickCommand":
|
|
150
|
+
"""
|
|
151
|
+
Generate ClickCommand from a click.Command
|
|
152
|
+
|
|
153
|
+
:param click.core.Command command: The click.Command to convert
|
|
154
|
+
:param bool include_callback: Whether to include the callback, defaults to True
|
|
155
|
+
:param bool include_command: Whether to include the command, defaults to False
|
|
156
|
+
:return: A ClickCommand object
|
|
157
|
+
:rtype: ClickCommand
|
|
158
|
+
"""
|
|
159
|
+
data = {
|
|
160
|
+
"command": command if include_command else None,
|
|
161
|
+
"name": command.name,
|
|
162
|
+
"help": command.help,
|
|
163
|
+
"options_metavar": command.options_metavar,
|
|
164
|
+
"context_settings": command.context_settings,
|
|
165
|
+
"params": {
|
|
166
|
+
param.name: ClickOption.from_option(param, include_callback)
|
|
167
|
+
for param in command.params
|
|
168
|
+
if isinstance(param, click.Option)
|
|
169
|
+
},
|
|
170
|
+
"signature": SignatureModel.from_callable(command=command.name, fn=command.callback),
|
|
171
|
+
"callback": (command.callback if include_callback else command.callback.__qualname__),
|
|
172
|
+
}
|
|
173
|
+
return cls(**data)
|
|
174
|
+
|
|
175
|
+
def _execute(self, *args, **kwargs) -> Optional[Any]:
|
|
176
|
+
"""
|
|
177
|
+
Execute the click command while suppressing SystemExit to prevent Airflow from exiting
|
|
178
|
+
|
|
179
|
+
:param args: The arguments to pass to the command
|
|
180
|
+
:param kwargs: The keyword arguments to pass to the command
|
|
181
|
+
:return: The result of the command
|
|
182
|
+
:rtype: Optional[Any]
|
|
183
|
+
"""
|
|
184
|
+
if not isinstance(self.callback, Callable):
|
|
185
|
+
raise RuntimeWarning("Callable not configured as callback")
|
|
186
|
+
with contextlib.suppress(SystemExit):
|
|
187
|
+
return self.callback(*args, **kwargs)
|
|
188
|
+
|
|
189
|
+
def _validate_params(self, *args, **kwargs) -> Tuple[list, dict]:
|
|
190
|
+
"""
|
|
191
|
+
Validate the params and represent them as a dict of key value pairs
|
|
192
|
+
|
|
193
|
+
:param args: The arguments to validate
|
|
194
|
+
:param kwargs: The keyword arguments to validate
|
|
195
|
+
:return: A tuple of the validated args and kwargs
|
|
196
|
+
:rtype: Tuple[list, dict]
|
|
197
|
+
"""
|
|
198
|
+
# iterate and get the expected list of params, if they are not Optional
|
|
199
|
+
param_values = []
|
|
200
|
+
param_dict = {}
|
|
201
|
+
for i, param in enumerate(self.params):
|
|
202
|
+
if args and i < len(args):
|
|
203
|
+
# process positional arguments first
|
|
204
|
+
param_values.append(args[i])
|
|
205
|
+
elif kwargs and param in kwargs:
|
|
206
|
+
# process keyword arguments
|
|
207
|
+
param_dict[param] = kwargs[param]
|
|
208
|
+
elif self.params[param].default is not None:
|
|
209
|
+
# use default for param if provided
|
|
210
|
+
param_dict[param] = self.params[param].default
|
|
211
|
+
else:
|
|
212
|
+
raise ValueError(f"Missing required argument {param}")
|
|
213
|
+
return param_values, param_dict
|
|
214
|
+
|
|
215
|
+
def call(self, *args, **kwargs) -> Optional[Any]:
|
|
216
|
+
"""
|
|
217
|
+
Call the callable for the command
|
|
218
|
+
|
|
219
|
+
:param args: The arguments to pass to the command
|
|
220
|
+
:param kwargs: The keyword arguments to pass to the command
|
|
221
|
+
:return: The result of the command
|
|
222
|
+
:rtype: Optional[Any]
|
|
223
|
+
"""
|
|
224
|
+
param_values, param_dict = self._validate_params(*args, **kwargs)
|
|
225
|
+
return self._execute(*param_values, **param_dict)
|
|
226
|
+
|
|
227
|
+
def return_cli_commands(self):
|
|
228
|
+
"""
|
|
229
|
+
Return a list of all cli_commands independent of hierarchy
|
|
230
|
+
|
|
231
|
+
:return: A list of all cli_commands
|
|
232
|
+
:rtype: list
|
|
233
|
+
"""
|
|
234
|
+
cli_commands = []
|
|
235
|
+
for param in self.params:
|
|
236
|
+
if isinstance(param, ClickCommand):
|
|
237
|
+
cli_commands.extend(param.return_cli_commands())
|
|
238
|
+
else:
|
|
239
|
+
cli_commands.append(param)
|
|
240
|
+
return cli_commands
|
|
241
|
+
|
|
242
|
+
@property
|
|
243
|
+
def param_defaults(self) -> dict:
|
|
244
|
+
"""Return a dictionary with basic defaults for the parameters
|
|
245
|
+
:return: A dict in the following form:
|
|
246
|
+
>>> {
|
|
247
|
+
"has_default": bool,
|
|
248
|
+
"default": option.default,
|
|
249
|
+
"required": bool,
|
|
250
|
+
"prompt": bool
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
for all options required by Click.
|
|
254
|
+
:rtype: dict
|
|
255
|
+
"""
|
|
256
|
+
return {
|
|
257
|
+
option.name: {
|
|
258
|
+
"has_default": bool(option.default),
|
|
259
|
+
"default": option.default,
|
|
260
|
+
"required": option.required,
|
|
261
|
+
"prompt": option.prompt,
|
|
262
|
+
}
|
|
263
|
+
for _, option in self.params.items()
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
def get_callback_args(self, putative_params: dict) -> dict:
|
|
267
|
+
"""Get the callback arguments from the dag_run configuration.
|
|
268
|
+
|
|
269
|
+
:param dict putative_params: The dag_run configuration and op_kwargs dictionary.
|
|
270
|
+
:return: A dictionary where each key is a parameter name and each value is either the default
|
|
271
|
+
value of the parameter (if it has one and if the parameter is not present in dag_run_conf),
|
|
272
|
+
or the value from dag_run_conf.
|
|
273
|
+
:rtype: dict
|
|
274
|
+
"""
|
|
275
|
+
callback_args = {}
|
|
276
|
+
|
|
277
|
+
if self.callback is not None and self.signatures is not None:
|
|
278
|
+
for _, param in self.signatures.parameters.items():
|
|
279
|
+
param_name = param.name
|
|
280
|
+
param_default = param.default
|
|
281
|
+
if param_name in putative_params:
|
|
282
|
+
callback_args[param_name] = putative_params[param_name]
|
|
283
|
+
elif param_default is not inspect.Parameter.empty:
|
|
284
|
+
callback_args[param_name] = param_default
|
|
285
|
+
|
|
286
|
+
return callback_args
|
|
287
|
+
|
|
288
|
+
@property
|
|
289
|
+
def parameters(self) -> List[str]:
|
|
290
|
+
"""
|
|
291
|
+
Return a list of parameters expected by this command
|
|
292
|
+
|
|
293
|
+
:return: A list of parameters
|
|
294
|
+
:rtype: List[str]
|
|
295
|
+
"""
|
|
296
|
+
signatures = self.signatures or []
|
|
297
|
+
params = self.params or []
|
|
298
|
+
return [param.name if hasattr(param, "name") else param for param in signatures] + [
|
|
299
|
+
param.name if hasattr(param, "name") else param for param in params
|
|
300
|
+
]
|
|
301
|
+
|
|
302
|
+
@property
|
|
303
|
+
def defaults(self) -> Dict[str, Any]:
|
|
304
|
+
"""
|
|
305
|
+
Return a dictionary of the defaults for each parameter
|
|
306
|
+
|
|
307
|
+
:return: A dictionary of the defaults for each parameter
|
|
308
|
+
:rtype: Dict[str, Any]
|
|
309
|
+
"""
|
|
310
|
+
return {param_name: option.default for param_name, option in self.params.items() if option.default is not None}
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
class ClickGroup(BaseModel):
|
|
314
|
+
"""BaseModel representation of a click Group"""
|
|
315
|
+
|
|
316
|
+
model_config = ConfigDict(extra="ignore", arbitrary_types_allowed=True)
|
|
317
|
+
|
|
318
|
+
name: str
|
|
319
|
+
group_name: str
|
|
320
|
+
# This double-quoted ClickGroup is a forward reference to allow for nested groups
|
|
321
|
+
commands: Dict[str, Union[ClickCommand, "ClickGroup"]]
|
|
322
|
+
|
|
323
|
+
@classmethod
|
|
324
|
+
def from_lazy_group(
|
|
325
|
+
cls,
|
|
326
|
+
cli: click.Group,
|
|
327
|
+
group: LazyGroup,
|
|
328
|
+
prefix: Optional[str] = None,
|
|
329
|
+
include_callback: bool = True,
|
|
330
|
+
) -> "ClickGroup":
|
|
331
|
+
"""
|
|
332
|
+
Define a ClickGroup based on a LazyGroup group
|
|
333
|
+
|
|
334
|
+
:param click.Group cli: The click.Group object, used for context and fetching click commands from LazyGroup
|
|
335
|
+
:param LazyGroup group: The LazyGroup object to convert to a ClickGroup
|
|
336
|
+
:param str prefix: The prefix to add to the group name
|
|
337
|
+
:param bool include_callback: Whether to include the callback for the group
|
|
338
|
+
:return: A ClickGroup object
|
|
339
|
+
:rtype: ClickGroup
|
|
340
|
+
"""
|
|
341
|
+
prefix = f"{prefix}__{group.name}" if prefix else f"{group.name}"
|
|
342
|
+
data = {
|
|
343
|
+
"name": prefix,
|
|
344
|
+
"group_name": group.name,
|
|
345
|
+
"commands": {},
|
|
346
|
+
}
|
|
347
|
+
for cmd_name in group.lazy_subcommands.keys():
|
|
348
|
+
cmd = group.get_command(cli.context_class, cmd_name) # noqa
|
|
349
|
+
if not cmd:
|
|
350
|
+
continue
|
|
351
|
+
if isinstance(cmd, click.core.Group):
|
|
352
|
+
data["commands"][cmd.name] = cls.from_group(cmd, include_callback) # noqa
|
|
353
|
+
elif isinstance(cmd, click.core.Command):
|
|
354
|
+
data["commands"][cmd.name] = ClickCommand.from_command(cmd, include_callback)
|
|
355
|
+
return cls(**data)
|
|
356
|
+
|
|
357
|
+
@classmethod
|
|
358
|
+
def from_group(
|
|
359
|
+
cls,
|
|
360
|
+
group: click.Group,
|
|
361
|
+
prefix: Optional[str] = None,
|
|
362
|
+
include_callback: bool = True,
|
|
363
|
+
) -> "ClickGroup":
|
|
364
|
+
"""
|
|
365
|
+
Define a ClickGroup based on a click.Group group
|
|
366
|
+
|
|
367
|
+
:param click.Group group: The click.Group object to convert to a ClickGroup
|
|
368
|
+
:param str prefix: The prefix to add to the group name
|
|
369
|
+
:param bool include_callback: Whether to include the callback for the group
|
|
370
|
+
:return: A ClickGroup object
|
|
371
|
+
:rtype: ClickGroup
|
|
372
|
+
"""
|
|
373
|
+
prefix = f"{prefix}__{group.name}" if prefix else f"{group.name}"
|
|
374
|
+
data = {
|
|
375
|
+
"name": prefix,
|
|
376
|
+
"group_name": group.name,
|
|
377
|
+
"commands": {},
|
|
378
|
+
}
|
|
379
|
+
for cmd_name, cmd in group.commands.items():
|
|
380
|
+
if not cmd:
|
|
381
|
+
continue
|
|
382
|
+
if isinstance(cmd, LazyGroup):
|
|
383
|
+
data["commands"][cmd_name] = cls.from_lazy_group(
|
|
384
|
+
group, cmd, prefix=prefix, include_callback=include_callback
|
|
385
|
+
)
|
|
386
|
+
elif isinstance(cmd, click.core.Group):
|
|
387
|
+
data["commands"][cmd.name] = cls.from_group(cmd, include_callback)
|
|
388
|
+
elif isinstance(cmd, click.core.Command):
|
|
389
|
+
data["commands"][cmd.name] = ClickCommand.from_command(cmd, include_callback)
|
|
390
|
+
return cls(**data)
|
|
391
|
+
|
|
392
|
+
def flatten(self, prefix: str = "") -> dict:
|
|
393
|
+
"""
|
|
394
|
+
Flatten the group to a dictionary of commands.
|
|
395
|
+
|
|
396
|
+
:param str prefix: The prefix to add to the group name
|
|
397
|
+
:return: A dictionary of commands
|
|
398
|
+
:rtype: dict
|
|
399
|
+
"""
|
|
400
|
+
commands = {}
|
|
401
|
+
|
|
402
|
+
def _flatten(group_: Union[ClickCommand, "ClickGroup"], prefix_: str = ""):
|
|
403
|
+
for cmd in group_.commands:
|
|
404
|
+
# flake8: noqa: F821
|
|
405
|
+
if isinstance(cmd, ClickCommand):
|
|
406
|
+
cmd_name = f"{prefix_}__{cmd.name}" if prefix_ else cmd.name
|
|
407
|
+
commands[cmd_name] = cmd
|
|
408
|
+
elif isinstance(cmd, ClickGroup):
|
|
409
|
+
new_prefix = f"{prefix_}__{cmd.group_name}" if prefix_ else cmd.group_name
|
|
410
|
+
_flatten(cmd, new_prefix)
|
|
411
|
+
|
|
412
|
+
_flatten(self, prefix)
|
|
413
|
+
return commands
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""Create the AppConfig objects."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from inspect import getmembers, currentframe, isclass
|
|
5
|
+
from pydantic import BaseModel, create_model, SecretStr
|
|
6
|
+
from regscale.models.platform import RegScaleAuth
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Provider(BaseModel):
|
|
10
|
+
"""A provider class"""
|
|
11
|
+
|
|
12
|
+
provider: str
|
|
13
|
+
|
|
14
|
+
def __getitem__(self, item):
|
|
15
|
+
"""Override the default getitem to modify the config dict object."""
|
|
16
|
+
self.__dict__.get(item)
|
|
17
|
+
|
|
18
|
+
def __setitem__(self, key, value):
|
|
19
|
+
"""Override the default setitem to modify the config dict object."""
|
|
20
|
+
self.__dict__[key] = value
|
|
21
|
+
|
|
22
|
+
def refresh(self):
|
|
23
|
+
"""Refresh this providers data"""
|
|
24
|
+
# TODO - implement the refresh method
|
|
25
|
+
raise NotImplementedError("coming soon!")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
providers = {
|
|
29
|
+
"AdProvider": {
|
|
30
|
+
"adAccessToken": (str, ...),
|
|
31
|
+
"adAuthUrl": (str, ...),
|
|
32
|
+
"adClientSecret": (SecretStr, ...),
|
|
33
|
+
"adClientId": (SecretStr, ...),
|
|
34
|
+
"adGraphURL": (str, ...),
|
|
35
|
+
},
|
|
36
|
+
"Azure365Provider": {
|
|
37
|
+
"azure365AccessToken": (str, ...),
|
|
38
|
+
"azure365ClientId": (SecretStr, ...),
|
|
39
|
+
"azure365TenantId": (str, ...),
|
|
40
|
+
},
|
|
41
|
+
"AzureCloudProvider": {
|
|
42
|
+
"azureCloudAccessToken": (SecretStr, ...),
|
|
43
|
+
"azureCloudClientId": (str, ...),
|
|
44
|
+
"azureCloudTenantId": (str, ...),
|
|
45
|
+
"azureCloudSubscriptionId": (SecretStr, ...),
|
|
46
|
+
},
|
|
47
|
+
"CisaProvider": {
|
|
48
|
+
"cisaKev": (
|
|
49
|
+
str,
|
|
50
|
+
"https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json",
|
|
51
|
+
),
|
|
52
|
+
"cisa_alerts": (str, "https://www.cisa.gov/uscert/ncas/alerts/"),
|
|
53
|
+
"cisa_kev": (
|
|
54
|
+
str,
|
|
55
|
+
"https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json",
|
|
56
|
+
),
|
|
57
|
+
},
|
|
58
|
+
"DependabotProvider": {
|
|
59
|
+
"dependabotId": (SecretStr, ...),
|
|
60
|
+
"dependabotOwner": (str, ...),
|
|
61
|
+
"dependabotRepo": (str, ...),
|
|
62
|
+
"dependabotToken": (SecretStr, ...),
|
|
63
|
+
},
|
|
64
|
+
"JiraProvider": {
|
|
65
|
+
"jiraApiToken": (SecretStr, ...),
|
|
66
|
+
"jiraUrl": (str, ...),
|
|
67
|
+
"jirUserName": (str, ...),
|
|
68
|
+
},
|
|
69
|
+
"OktaProvider": {
|
|
70
|
+
"oktaApiToken": (SecretStr, ...),
|
|
71
|
+
"oktaClientId": (str, ...),
|
|
72
|
+
"oktaUrl": (str, ...),
|
|
73
|
+
},
|
|
74
|
+
"QualysProvider": {
|
|
75
|
+
"qualysURL": (str, ...),
|
|
76
|
+
"qualysUserName": (str, ...),
|
|
77
|
+
"qualysPassword": (SecretStr, ...),
|
|
78
|
+
},
|
|
79
|
+
"SnowProvider": {
|
|
80
|
+
"snowPassword": (SecretStr, ...),
|
|
81
|
+
"snowUserName": (str, ...),
|
|
82
|
+
"snowUrl": (str, ...),
|
|
83
|
+
},
|
|
84
|
+
"SonarProvider": {
|
|
85
|
+
"sonarToken": (SecretStr, ...),
|
|
86
|
+
},
|
|
87
|
+
"TenableProvider": {
|
|
88
|
+
# FIXME - [sic] in mistake below, key is lowercase
|
|
89
|
+
"tenableAccesskey": (SecretStr, ...),
|
|
90
|
+
"tenableSecretkey": (SecretStr, ...),
|
|
91
|
+
"tenableUrl": (str, "https://sc.tenable.online"),
|
|
92
|
+
},
|
|
93
|
+
"WizProvider": {
|
|
94
|
+
"wizAccessToken": (SecretStr, ...),
|
|
95
|
+
"wizAuthUrl": (str, "https://auth.wiz.io/oauth/token"),
|
|
96
|
+
"wizExcludes": (str, ""),
|
|
97
|
+
"wizReportAge": (int, 15),
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
# the above dict is itemized, and the key for each dict is assigned
|
|
102
|
+
# a new class with the sub-dict as kwargs to the Provider class
|
|
103
|
+
# the tuple of each sub-dict key defines the type and the default
|
|
104
|
+
# if ... is supplied, there is no default and it is required
|
|
105
|
+
for provider_name, fields in providers.items():
|
|
106
|
+
# Add or override fields in the provider's dictionary
|
|
107
|
+
updated_fields = {}
|
|
108
|
+
for field_name, (field_type, default_value) in fields.items():
|
|
109
|
+
# Use the field_type and default_value from the tuple
|
|
110
|
+
if default_value is ...: # Checking if the field is required
|
|
111
|
+
updated_fields[field_name] = (field_type, ...)
|
|
112
|
+
else:
|
|
113
|
+
updated_fields[field_name] = (field_type, default_value)
|
|
114
|
+
|
|
115
|
+
# Add the 'provider' field with its type and value
|
|
116
|
+
provider_key = provider_name.split("Provider")[0].lower()
|
|
117
|
+
updated_fields["provider"] = (str, provider_key)
|
|
118
|
+
|
|
119
|
+
# Create the model with the updated fields
|
|
120
|
+
globals()[provider_name] = create_model(provider_name, **updated_fields, __base__=Provider)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class Providers(BaseModel):
|
|
124
|
+
pass
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# generate a hidden dict of classes for all classes currently defined
|
|
128
|
+
_all_classes = {name: obj for name, obj in getmembers(currentframe().f_globals) if isclass(obj)}
|
|
129
|
+
# iterate over the provider keys, and add an Optional dynamically created provider class
|
|
130
|
+
for provider in providers.keys():
|
|
131
|
+
if provider in _all_classes:
|
|
132
|
+
Providers.__annotations__[provider.split("Provider")[0].lower()] = Optional[_all_classes[provider]]
|
|
133
|
+
# now any provider class is a parameter to Providers, so
|
|
134
|
+
# providers = Providers(wiz=WizProvider(...), ad=AdProvider(...))
|
|
135
|
+
# providers.wiz.wizAccessToken will access the access token in the providers class
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class AppConfig(BaseModel):
|
|
139
|
+
"""The AppConfig object will be used to generate the config for platform interaction"""
|
|
140
|
+
|
|
141
|
+
auth: RegScaleAuth
|
|
142
|
+
config: Optional[dict] = None # TODO - Spec this as a BaseModel too
|
|
143
|
+
providers: Optional[Providers] = None # TODO - spec providers and implement
|
|
144
|
+
# with the providers we can access values like AppConfig.providers.wiz.wizAccessToken
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def token(self):
|
|
148
|
+
return self.auth.token
|
|
149
|
+
|
|
150
|
+
@classmethod
|
|
151
|
+
def populate(cls):
|
|
152
|
+
"""Class method to populate the AppConfig class"""
|
|
153
|
+
# TODO implement method for retrieving config from platform
|
|
154
|
+
return cls()
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
h1 {
|
|
3
|
+
color: #0A63B3;
|
|
4
|
+
font-size: 1.51rem;
|
|
5
|
+
font-family: Roboto, "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
|
6
|
+
font-family-monospace: Roboto, "Montserrat", Georgia, "Times New Roman", Times, serif;
|
|
7
|
+
font-weight: normal;
|
|
8
|
+
margin-bottom: -10px;
|
|
9
|
+
}
|
|
10
|
+
table {
|
|
11
|
+
font-family: Roboto, "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
|
12
|
+
font-family-monospace: Roboto, "Montserrat", Georgia, "Times New Roman", Times, serif;
|
|
13
|
+
margin: 5px;
|
|
14
|
+
border-collapse: collapse;
|
|
15
|
+
border-color: 0;
|
|
16
|
+
color: #404E67;
|
|
17
|
+
}
|
|
18
|
+
th {
|
|
19
|
+
border-bottom: 1px solid #E2EBF3;
|
|
20
|
+
padding: 10px 15px;
|
|
21
|
+
font-family: Roboto, "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
|
22
|
+
font-family-monospace: Roboto, "Montserrat", Georgia, "Times New Roman", Times, serif;
|
|
23
|
+
font-weight: 600;
|
|
24
|
+
font-size: 1rem;
|
|
25
|
+
color: #404E67;
|
|
26
|
+
}
|
|
27
|
+
tr, td {
|
|
28
|
+
background-color: white;
|
|
29
|
+
color: #404E67;
|
|
30
|
+
font-size: 14px;
|
|
31
|
+
font-family: Roboto, "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
|
32
|
+
font-family-monospace: Roboto, "Montserrat", Georgia, "Times New Roman", Times, serif;
|
|
33
|
+
font-weight: 400;
|
|
34
|
+
padding: 10px;
|
|
35
|
+
text-align: center;
|
|
36
|
+
border-bottom: 1px solid #E2EBF3;
|
|
37
|
+
}
|
|
38
|
+
a {
|
|
39
|
+
mso-hide: all;
|
|
40
|
+
text-align: center;
|
|
41
|
+
font-size: 14px;
|
|
42
|
+
font-weight: 450;
|
|
43
|
+
background-color: #1DC3EB;
|
|
44
|
+
color: white;
|
|
45
|
+
border: 1px solid #22C2DC;
|
|
46
|
+
border-radius: 5px;
|
|
47
|
+
margin: 2px;
|
|
48
|
+
padding: 5px 10px;
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
|
51
|
+
box-shadow: 1px 2px 5px 1px rgba(0, 0, 0, 0.11);
|
|
52
|
+
}
|
|
53
|
+
a:active {
|
|
54
|
+
background-color: yellow;
|
|
55
|
+
}
|
|
56
|
+
a:hover {
|
|
57
|
+
background-color: #4CD5E7;
|
|
58
|
+
color: #FAF9F6;
|
|
59
|
+
}
|
|
60
|
+
a:visited {
|
|
61
|
+
color: #FFFFFF;
|
|
62
|
+
background-color: #A8B8C7;
|
|
63
|
+
}
|
|
64
|
+
a:visited:hover {
|
|
65
|
+
background-color:#79848F;
|
|
66
|
+
}
|
|
67
|
+
</style>
|