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,582 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""standard python imports"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
7
|
+
from json import JSONDecodeError
|
|
8
|
+
from typing import Any, List
|
|
9
|
+
|
|
10
|
+
import requests
|
|
11
|
+
from lxml.etree import Element
|
|
12
|
+
from packaging.version import Version
|
|
13
|
+
|
|
14
|
+
from regscale.core.app.application import Application
|
|
15
|
+
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
16
|
+
from regscale.integrations.public.fedramp.fedramp_traversal import FedrampTraversal
|
|
17
|
+
from regscale.models.regscale_models.control_implementation import ControlImplementation
|
|
18
|
+
from regscale.models.regscale_models.implementation_objective import ImplementationObjective
|
|
19
|
+
from regscale.models.regscale_models.implementation_option import ImplementationOptionDeprecated
|
|
20
|
+
from regscale.models.regscale_models.security_plan import SecurityPlan
|
|
21
|
+
from regscale.utils.version import RegscaleVersion
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger("regscale")
|
|
24
|
+
|
|
25
|
+
FULLY_IMPLEMENTED = "Fully Implemented"
|
|
26
|
+
NOT_IMPLEMENTED = "Not Implemented"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def get_parts_list(ele: Any) -> list[dict]:
|
|
30
|
+
"""
|
|
31
|
+
Get the parts list
|
|
32
|
+
|
|
33
|
+
:param Any ele: The element
|
|
34
|
+
:return: A list of parts
|
|
35
|
+
:rtype: list[dict]
|
|
36
|
+
"""
|
|
37
|
+
oscal_component = ".//oscal:by-component"
|
|
38
|
+
parts_list = []
|
|
39
|
+
nsmap = {"oscal": "http://csrc.nist.gov/ns/oscal/1.0"}
|
|
40
|
+
statements = ele.xpath("//*[contains(@statement-id, 'smt')]", namespaces=nsmap)
|
|
41
|
+
parameters = ele.xpath("//*[contains(@param-id, 'prm') or contains(@param-id, 'odp')]", namespaces=nsmap)
|
|
42
|
+
objectives = ele.xpath("//*[contains(@statement-id, 'obj')]", namespaces=nsmap)
|
|
43
|
+
|
|
44
|
+
for statement in statements:
|
|
45
|
+
parts = {}
|
|
46
|
+
component_uuid = statement.xpath(oscal_component, namespaces=nsmap)[0].attrib["component-uuid"]
|
|
47
|
+
parts["part_id"] = statement.attrib["statement-id"]
|
|
48
|
+
parts["uuid"] = statement.attrib["uuid"]
|
|
49
|
+
if component_uuid:
|
|
50
|
+
parts["component_uuid"] = component_uuid
|
|
51
|
+
p_texts = statement.xpath(
|
|
52
|
+
".//oscal:by-component/oscal:description/oscal:p/text()",
|
|
53
|
+
namespaces=nsmap,
|
|
54
|
+
)
|
|
55
|
+
parts["text"] = p_texts
|
|
56
|
+
if statement.attrib["statement-id"] not in {part["part_id"] for part in parts_list}:
|
|
57
|
+
parts_list.append(parts)
|
|
58
|
+
|
|
59
|
+
for objective in objectives:
|
|
60
|
+
parts = {}
|
|
61
|
+
parts["part_id"] = objective.attrib["statement-id"]
|
|
62
|
+
comp = objective.xpath(oscal_component, namespaces=nsmap)
|
|
63
|
+
if comp:
|
|
64
|
+
component_uuid = comp[0].attrib["component-uuid"]
|
|
65
|
+
b_texts = objective.xpath(
|
|
66
|
+
".//oscal:by-component/oscal:description/oscal:p/text()",
|
|
67
|
+
namespaces=nsmap,
|
|
68
|
+
)
|
|
69
|
+
parts["text"] = b_texts
|
|
70
|
+
if component_uuid:
|
|
71
|
+
parts["component_uuid"] = component_uuid
|
|
72
|
+
if objective.attrib["statement-id"] not in {part["part_id"] for part in parts_list}:
|
|
73
|
+
parts_list.append(parts)
|
|
74
|
+
|
|
75
|
+
for parameter in parameters:
|
|
76
|
+
parts = {}
|
|
77
|
+
parts["part_id"] = parameter.attrib["param-id"]
|
|
78
|
+
comp = parameter.xpath(oscal_component, namespaces=nsmap)
|
|
79
|
+
if comp:
|
|
80
|
+
component_uuid = comp[0].attrib["component-uuid"]
|
|
81
|
+
b_texts = parameter.xpath(
|
|
82
|
+
".//oscal:set-parameter/value/text()",
|
|
83
|
+
namespaces=nsmap,
|
|
84
|
+
)
|
|
85
|
+
b_texts = parameter.xpath(
|
|
86
|
+
".//oscal:value/text()",
|
|
87
|
+
namespaces=nsmap,
|
|
88
|
+
)
|
|
89
|
+
if b_texts:
|
|
90
|
+
parts["text"] = b_texts.pop()
|
|
91
|
+
if component_uuid:
|
|
92
|
+
parts["component_uuid"] = component_uuid
|
|
93
|
+
if parameter.attrib["param-id"] not in {part["part_id"] for part in parts_list}:
|
|
94
|
+
parts_list.append(parts)
|
|
95
|
+
return parts_list
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def get_maps() -> tuple:
|
|
99
|
+
"""
|
|
100
|
+
Get the status and responsibility maps
|
|
101
|
+
|
|
102
|
+
:return: A tuple of status and responsibility maps
|
|
103
|
+
:rtype: tuple
|
|
104
|
+
"""
|
|
105
|
+
status_map = {
|
|
106
|
+
FULLY_IMPLEMENTED: "Implemented",
|
|
107
|
+
"Partially Implemented": "Partially Implemented",
|
|
108
|
+
"Not Applicable": "Not Applicable",
|
|
109
|
+
NOT_IMPLEMENTED: NOT_IMPLEMENTED,
|
|
110
|
+
"Planned": "Planned",
|
|
111
|
+
}
|
|
112
|
+
responsibility_map = {
|
|
113
|
+
"Provider": "Service Provider Corporate",
|
|
114
|
+
"Provider (System Specific)": "Service Provider System Specific",
|
|
115
|
+
"Customer": "Provided by Customer (Customer System Specific)",
|
|
116
|
+
"Hybrid": "Service Provider Hybrid (Corporate and System Specific)",
|
|
117
|
+
"Customer Configured": "Configured by Customer (Customer System Specific)",
|
|
118
|
+
"Shared": "Shared (Service Provider and Customer Responsibility)",
|
|
119
|
+
"Inherited": "Inherited from pre-existing FedRAMP Authorization",
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return status_map, responsibility_map
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def fetch_implementations(trv: FedrampTraversal, root: Element, ssp: SecurityPlan) -> list:
|
|
126
|
+
"""
|
|
127
|
+
Fetch the control implementations for the provided SSP in RegScale
|
|
128
|
+
|
|
129
|
+
:param FedrampTraversal trv: FedrampTraversal instance
|
|
130
|
+
:param Element root: The root element of the OSCAL document
|
|
131
|
+
:param SecurityPlan ssp: RegScale security plan object
|
|
132
|
+
:return: List of control implementations
|
|
133
|
+
:rtype: list
|
|
134
|
+
"""
|
|
135
|
+
app = trv.api.app
|
|
136
|
+
api = trv.api
|
|
137
|
+
# Compliance settings groups are too inconsistent to auto map, so we need to manually map them
|
|
138
|
+
status_map, responsibility_map = get_maps()
|
|
139
|
+
ns = {"ns1": "http://csrc.nist.gov/ns/oscal/1.0"}
|
|
140
|
+
parts = []
|
|
141
|
+
imps = []
|
|
142
|
+
reqs = root.xpath("//ns1:implemented-requirement", namespaces=ns)
|
|
143
|
+
ssp.parentId = trv.catalogue_id
|
|
144
|
+
ssp.parentModule = "catalogues"
|
|
145
|
+
cat_id = ssp.parentId
|
|
146
|
+
detail = {}
|
|
147
|
+
trv.log_info(
|
|
148
|
+
{
|
|
149
|
+
"model_layer": "System Control Implementation",
|
|
150
|
+
"record_type": "Control Implementation",
|
|
151
|
+
"event_msg": "Pulling Catalog details.",
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
detail_res = api.get(url=app.config["domain"] + f"/api/catalogues/getCatalogWithAllDetails/{cat_id}")
|
|
156
|
+
if detail_res.ok:
|
|
157
|
+
try:
|
|
158
|
+
detail = detail_res.json()
|
|
159
|
+
except JSONDecodeError as jex:
|
|
160
|
+
logger.error(jex)
|
|
161
|
+
return
|
|
162
|
+
control_objectives = detail["objectives"] if "objectives" in detail else []
|
|
163
|
+
options = detail["options"] if "options" in detail else []
|
|
164
|
+
existing_parameters = detail["parameters"] if "parameters" in detail else []
|
|
165
|
+
existing_controls = detail["controls"] if "controls" in detail else []
|
|
166
|
+
# Build options if they do not exist
|
|
167
|
+
updated_options = build_options(app=app, existing_options=options, control_objectives=control_objectives)
|
|
168
|
+
options.extend(updated_options)
|
|
169
|
+
|
|
170
|
+
new_options = post_options(trv, updated_options)
|
|
171
|
+
options.extend(new_options)
|
|
172
|
+
# TODO: Pull the options for just the control objectives we are working with.
|
|
173
|
+
# Get Parts data, mapped to a compoment id.
|
|
174
|
+
uuid = ""
|
|
175
|
+
for req in reqs:
|
|
176
|
+
for name, value in req.attrib.items():
|
|
177
|
+
if name == "uuid":
|
|
178
|
+
uuid = value
|
|
179
|
+
if name == "control-id":
|
|
180
|
+
logger.debug(f"Property: {name}, Value: {value}")
|
|
181
|
+
if ssp.parentModule == "catalogues":
|
|
182
|
+
logger.info("Building implementation: %s", value)
|
|
183
|
+
|
|
184
|
+
# This try catch is tied to modification to catalogs object returned by above API call
|
|
185
|
+
# The otherId field is to be added to new OSCAL catalogs which will be migrated for existing customers.
|
|
186
|
+
# If otherId exists use it to match to control otherwise use original controlId
|
|
187
|
+
# Handle case where otherId does not exist in catalog object and do not throw an error
|
|
188
|
+
# if otherid exists in catalog object make sure it has something in it before matching
|
|
189
|
+
# this case may exist while new catalogs are being migrated to for customers
|
|
190
|
+
matching_controls = [
|
|
191
|
+
control for control in existing_controls if control.get("otherId", "") == value
|
|
192
|
+
]
|
|
193
|
+
if not matching_controls:
|
|
194
|
+
matching_controls = [
|
|
195
|
+
control for control in existing_controls if control.get("controlId", "") == value
|
|
196
|
+
]
|
|
197
|
+
|
|
198
|
+
control = matching_controls[0] if matching_controls else None
|
|
199
|
+
|
|
200
|
+
if control is None:
|
|
201
|
+
trv.log_error(
|
|
202
|
+
{
|
|
203
|
+
"record_type": "System Control Implementation",
|
|
204
|
+
"event_msg": f"Failed to locate control {value} in the selected profile.",
|
|
205
|
+
"missing_element": f"Control {value}",
|
|
206
|
+
"model_layer": "System Control Implementation",
|
|
207
|
+
}
|
|
208
|
+
)
|
|
209
|
+
logger.warning("Unable to find a control, do you have a catalog?")
|
|
210
|
+
break
|
|
211
|
+
|
|
212
|
+
implementation = ControlImplementation.from_oscal_element(app=app, obj=req, control=control)
|
|
213
|
+
implementation.parentId = ssp.id
|
|
214
|
+
implementation.uuid = uuid
|
|
215
|
+
implementation.parentModule = "securityplans"
|
|
216
|
+
|
|
217
|
+
implementation.controlOwnerId = app.config["userId"]
|
|
218
|
+
|
|
219
|
+
# do a version check to use new compliance settings
|
|
220
|
+
regscale_version = RegscaleVersion.get_platform_version()
|
|
221
|
+
if len(regscale_version) >= 10 or Version(regscale_version) >= Version("6.13.0.0"):
|
|
222
|
+
implementation.status = status_map.get(implementation.status.value)
|
|
223
|
+
implementation.responsibility = responsibility_map.get(implementation.responsibility.value)
|
|
224
|
+
imps.append(implementation)
|
|
225
|
+
if control is None:
|
|
226
|
+
logger.error("Unable to locate the control in RegScale.")
|
|
227
|
+
|
|
228
|
+
parts.extend(get_parts_list(req))
|
|
229
|
+
|
|
230
|
+
logger.info("Loading control implementations to RegScale")
|
|
231
|
+
num_successful_post = 0
|
|
232
|
+
num_failed_post = 0
|
|
233
|
+
with ThreadPoolExecutor(max_workers=10) as executor:
|
|
234
|
+
post_futures = {
|
|
235
|
+
executor.submit(ControlImplementation.post_implementation, app=app, implementation=imp): imp for imp in imps
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
for future in as_completed(post_futures):
|
|
239
|
+
imp = post_futures[future]
|
|
240
|
+
try:
|
|
241
|
+
data = future.result()
|
|
242
|
+
if data is not None:
|
|
243
|
+
num_successful_post += 1
|
|
244
|
+
except Exception as ex:
|
|
245
|
+
logger.warning(f"An error occurred while posting implementation {imp}: {ex}")
|
|
246
|
+
num_failed_post += 1
|
|
247
|
+
else:
|
|
248
|
+
logger.info(f"Finished posting Implementation {num_successful_post} to RegScale")
|
|
249
|
+
|
|
250
|
+
trv.log_info(
|
|
251
|
+
{
|
|
252
|
+
"model_layer": "System Control Implementation",
|
|
253
|
+
"record_type": "Control Implementation",
|
|
254
|
+
"event_msg": f"Finished loading {num_successful_post} Control Implementations (Failed: {num_failed_post})",
|
|
255
|
+
}
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
logger.info("Processing Control Parts...")
|
|
259
|
+
imps = ControlImplementation.fetch_existing_implementations(
|
|
260
|
+
app=app, regscale_parent_id=ssp.id, regscale_module="securityplans"
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
process_parts(
|
|
264
|
+
trv,
|
|
265
|
+
control_objectives,
|
|
266
|
+
existing_parameters,
|
|
267
|
+
parts,
|
|
268
|
+
imps,
|
|
269
|
+
options,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
# Update implementation options with implementation objectives.
|
|
273
|
+
return imps
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def process_parts(
|
|
277
|
+
trv: FedrampTraversal,
|
|
278
|
+
control_objectives: List[dict],
|
|
279
|
+
existing_parameters: List[dict],
|
|
280
|
+
parts: List[dict],
|
|
281
|
+
imps: List[dict],
|
|
282
|
+
single_system: bool = True,
|
|
283
|
+
):
|
|
284
|
+
"""
|
|
285
|
+
Process parts of the implementation
|
|
286
|
+
|
|
287
|
+
:param FedrampTraversal trv: FedrampTraversal instance
|
|
288
|
+
:param List[dict] control_objectives: A list of control objectives
|
|
289
|
+
:param List[dict] existing_parameters: A list of existing parameters
|
|
290
|
+
:param List[dict] parts: A list of parts
|
|
291
|
+
:param List[dict] imps: A list of implementations
|
|
292
|
+
:param bool single_system: A flag to indicate if the system is a single system, defaults to True
|
|
293
|
+
"""
|
|
294
|
+
app = trv.api.app
|
|
295
|
+
api = trv.api
|
|
296
|
+
config = app.config
|
|
297
|
+
implementation_objectives = []
|
|
298
|
+
all_params = []
|
|
299
|
+
|
|
300
|
+
for imp in imps:
|
|
301
|
+
status = imp["status"]
|
|
302
|
+
imp_id = imp["id"]
|
|
303
|
+
|
|
304
|
+
logger.info(f"Loading parts for {imp['controlName']}...")
|
|
305
|
+
|
|
306
|
+
part_notes = [
|
|
307
|
+
part
|
|
308
|
+
for part in parts
|
|
309
|
+
if "smt" in part["part_id"]
|
|
310
|
+
and imp["controlName"] == part["part_id"].split("_")[0]
|
|
311
|
+
and "_smt" in part["part_id"]
|
|
312
|
+
]
|
|
313
|
+
|
|
314
|
+
params = [
|
|
315
|
+
part
|
|
316
|
+
for part in parts
|
|
317
|
+
if (
|
|
318
|
+
("prm" in part["part_id"] and imp["controlName"] == part["part_id"].split("_prm")[0])
|
|
319
|
+
or (
|
|
320
|
+
"odp" in part["part_id"]
|
|
321
|
+
and imp["controlName"] == part["part_id"].replace("-0", "-").split("_odp")[0]
|
|
322
|
+
)
|
|
323
|
+
)
|
|
324
|
+
]
|
|
325
|
+
parameters = [dict(t) for t in set(tuple(d.items()) for d in params)]
|
|
326
|
+
|
|
327
|
+
# Just load statement parts _smt parts
|
|
328
|
+
for part in part_notes:
|
|
329
|
+
prefix = part["part_id"].split("_")[0]
|
|
330
|
+
control_objectives_items = {
|
|
331
|
+
obj["name"]: obj
|
|
332
|
+
for obj in control_objectives
|
|
333
|
+
if obj["name"].startswith(f"{prefix}_smt") or "_fr_smt" in obj["name"]
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
c_objective = control_objectives_items.get(part.get("part_id"))
|
|
337
|
+
if c_objective is None:
|
|
338
|
+
continue
|
|
339
|
+
cntrl_objectives = [obj for obj in control_objectives if obj["name"] == part["part_id"]]
|
|
340
|
+
status_map, _ = get_maps()
|
|
341
|
+
regscale_version = RegscaleVersion.get_platform_version()
|
|
342
|
+
if len(regscale_version) >= 10 or Version(regscale_version) >= Version("6.13.0.0"):
|
|
343
|
+
status = status_map.get(status)
|
|
344
|
+
|
|
345
|
+
if cntrl_objectives:
|
|
346
|
+
imp_objective = ImplementationObjective(
|
|
347
|
+
notes=part["part_id"],
|
|
348
|
+
status=status,
|
|
349
|
+
implementationId=imp_id,
|
|
350
|
+
# optionId=option["id"],
|
|
351
|
+
securityControlId=imp["controlID"],
|
|
352
|
+
objectiveId=c_objective["id"], # controlObjective['id]
|
|
353
|
+
id=0,
|
|
354
|
+
uuid=part["uuid"],
|
|
355
|
+
createdById=config["userId"],
|
|
356
|
+
statement=part["text"].pop() if part["text"] else "",
|
|
357
|
+
# TODO: Find and update these data fields.
|
|
358
|
+
authorizationId=None,
|
|
359
|
+
responsibility=None,
|
|
360
|
+
cloudResponsibility=None,
|
|
361
|
+
customerResponsibility=None,
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
if imp_objective not in implementation_objectives:
|
|
365
|
+
implementation_objectives.append(imp_objective)
|
|
366
|
+
|
|
367
|
+
params = update_parameters(trv, existing_parameters, parameters, imp)
|
|
368
|
+
all_params.extend(params)
|
|
369
|
+
post_params(trv, all_params)
|
|
370
|
+
|
|
371
|
+
trv.log_info(
|
|
372
|
+
{
|
|
373
|
+
"model_layer": "System Control Implementation",
|
|
374
|
+
"record_type": "Implementation Objective",
|
|
375
|
+
"event_msg": f"Finished loading {len(implementation_objectives)} Implementation Objectives",
|
|
376
|
+
}
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
def post_objective(obj: ImplementationObjective) -> requests.Response:
|
|
380
|
+
"""
|
|
381
|
+
Post an objective to RegScale
|
|
382
|
+
|
|
383
|
+
:param ImplementationObjective obj: An implementation objective
|
|
384
|
+
:return: A response
|
|
385
|
+
:rtype: requests.Response
|
|
386
|
+
"""
|
|
387
|
+
url = config["domain"] + "/api/implementationObjectives"
|
|
388
|
+
return api.post(url=url, json=obj.__dict__)
|
|
389
|
+
|
|
390
|
+
num_impl_success = 0
|
|
391
|
+
num_impl_failed = 0
|
|
392
|
+
for obj in implementation_objectives:
|
|
393
|
+
response = post_objective(obj)
|
|
394
|
+
if not response:
|
|
395
|
+
num_impl_failed += 1
|
|
396
|
+
else:
|
|
397
|
+
num_impl_success += 1
|
|
398
|
+
|
|
399
|
+
trv.log_info(
|
|
400
|
+
{
|
|
401
|
+
"model_layer": "System Control Implementation",
|
|
402
|
+
"record_type": "Implementation Objective",
|
|
403
|
+
"event_msg": f"Finished posting {num_impl_success} Implementation Objectives (Failed: {num_impl_failed})",
|
|
404
|
+
}
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def post_params(trv: FedrampTraversal, params: List[dict]):
|
|
409
|
+
"""
|
|
410
|
+
Post Parameters to RegScale
|
|
411
|
+
|
|
412
|
+
:param FedrampTraversal trv: FedrampTraversal instance
|
|
413
|
+
:param List[dict] params: A list of parameters to post
|
|
414
|
+
"""
|
|
415
|
+
|
|
416
|
+
def post_parameter(param: dict) -> requests.Response:
|
|
417
|
+
"""
|
|
418
|
+
Post a parameter to RegScale
|
|
419
|
+
|
|
420
|
+
:param dict param: A parameter
|
|
421
|
+
:return: A response
|
|
422
|
+
:rtype: requests.Response
|
|
423
|
+
"""
|
|
424
|
+
url = trv.api.app.config["domain"] + "/api/parameters"
|
|
425
|
+
return trv.api.post(url=url, json=param)
|
|
426
|
+
|
|
427
|
+
logger.info("Posting %i Parameters to RegScale", len(params))
|
|
428
|
+
num_params_success = 0
|
|
429
|
+
num_params_failed = 0
|
|
430
|
+
with ThreadPoolExecutor(max_workers=10) as executor: # Increase the number of workers
|
|
431
|
+
post_futures = {executor.submit(post_parameter, param): param for param in params}
|
|
432
|
+
|
|
433
|
+
for future in as_completed(post_futures):
|
|
434
|
+
param = post_futures[future]
|
|
435
|
+
try:
|
|
436
|
+
data = future.result()
|
|
437
|
+
if data is not None:
|
|
438
|
+
num_params_success += 1
|
|
439
|
+
except Exception as ex:
|
|
440
|
+
logger.debug(f"An error occurred while posting parameter {param}: {ex}")
|
|
441
|
+
num_params_failed += 1
|
|
442
|
+
|
|
443
|
+
trv.log_info(
|
|
444
|
+
{
|
|
445
|
+
"model_layer": "System Control Implementation",
|
|
446
|
+
"record_type": "Parameters",
|
|
447
|
+
"event_msg": f"Finished posting {num_params_success} Parameters (Failed: {num_params_failed})",
|
|
448
|
+
}
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def update_parameters(
|
|
453
|
+
trv: FedrampTraversal, existing_parameters: List[dict], parameters: List[dict], imp: dict
|
|
454
|
+
) -> list[dict]:
|
|
455
|
+
"""
|
|
456
|
+
Update parameters
|
|
457
|
+
|
|
458
|
+
:param FedrampTraversal trv: FedrampTraversal instance
|
|
459
|
+
:param List[dict] existing_parameters: A list of existing parameters
|
|
460
|
+
:param List[dict] parameters: A list of parameters
|
|
461
|
+
:param dict imp: An implementation object
|
|
462
|
+
:return: A list of updated parameters
|
|
463
|
+
:rtype: list[dict]
|
|
464
|
+
"""
|
|
465
|
+
app = trv.api.app
|
|
466
|
+
new_params = []
|
|
467
|
+
|
|
468
|
+
for param in parameters:
|
|
469
|
+
dat = [
|
|
470
|
+
par
|
|
471
|
+
for par in existing_parameters
|
|
472
|
+
if par["parameterId"] == param["part_id"] and par["securityControlId"] == imp["controlID"]
|
|
473
|
+
]
|
|
474
|
+
if dat:
|
|
475
|
+
param["default"] = dat[0]["text"]
|
|
476
|
+
new_param = {
|
|
477
|
+
"id": 0,
|
|
478
|
+
"uuid": "",
|
|
479
|
+
"name": param["part_id"],
|
|
480
|
+
"value": param["text"],
|
|
481
|
+
"controlImplementationId": imp["id"],
|
|
482
|
+
"createdById": app.config["userId"],
|
|
483
|
+
"lastUpdatedById": app.config["userId"],
|
|
484
|
+
}
|
|
485
|
+
new_params.append(new_param)
|
|
486
|
+
return new_params
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def get_control_objectives(control_id: int, existing_objectives: List[dict]) -> List[dict]:
|
|
490
|
+
"""
|
|
491
|
+
Return control objectives for a given control ID
|
|
492
|
+
|
|
493
|
+
:param int control_id: id to fetch objectives for
|
|
494
|
+
:param List[dict] existing_objectives: A list of existing objectives
|
|
495
|
+
:return: A list of control objectives
|
|
496
|
+
:rtype: List[dict]
|
|
497
|
+
"""
|
|
498
|
+
return [obj for obj in existing_objectives if obj["securityControlId"] == control_id]
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
def post_options(trv: FedrampTraversal, options: list[ImplementationOptionDeprecated]) -> list[dict]:
|
|
502
|
+
"""
|
|
503
|
+
Post Implementation Option to RegScale
|
|
504
|
+
|
|
505
|
+
:param FedrampTraversal trv: FedrampTraversal object
|
|
506
|
+
:param list[ImplementationOptionDeprecated] options: A list of Implementation Options
|
|
507
|
+
:return: A list of responses
|
|
508
|
+
:rtype: list[dict]
|
|
509
|
+
"""
|
|
510
|
+
api = trv.api
|
|
511
|
+
res = []
|
|
512
|
+
num_options_success = 0
|
|
513
|
+
num_options_failed = 0
|
|
514
|
+
num_duplicates = 0
|
|
515
|
+
with ThreadPoolExecutor(max_workers=10) as executor: # Increase the number of workers
|
|
516
|
+
post_futures = {executor.submit(dt.insert, api): dt for dt in options}
|
|
517
|
+
|
|
518
|
+
for future in as_completed(post_futures):
|
|
519
|
+
dt = post_futures[future]
|
|
520
|
+
try:
|
|
521
|
+
response = future.result()
|
|
522
|
+
if not response.raise_for_status():
|
|
523
|
+
res.append(response.json())
|
|
524
|
+
logger.debug(
|
|
525
|
+
"Created a New Implementation Option: #%i",
|
|
526
|
+
response.json()["id"],
|
|
527
|
+
)
|
|
528
|
+
num_options_success += 1
|
|
529
|
+
except Exception as ex:
|
|
530
|
+
# rev 5 contains multiple parts for each control with implemention options
|
|
531
|
+
# there will be duplicates (which is ok)
|
|
532
|
+
# do not log a message but count them.
|
|
533
|
+
if response.status_code != 400 and "Duplicate" not in response.text:
|
|
534
|
+
logger.warning(f"An error occurred while posting data {dt}: {ex}")
|
|
535
|
+
num_options_failed += 1
|
|
536
|
+
else:
|
|
537
|
+
num_duplicates += 1
|
|
538
|
+
|
|
539
|
+
trv.log_info(
|
|
540
|
+
{
|
|
541
|
+
"model_layer": "System Control Implementation",
|
|
542
|
+
"record_type": "Implementation Option",
|
|
543
|
+
"event_msg": f"Finished posting {num_options_success} Implementation Options (Failed: {num_options_failed} Duplicates: {num_duplicates})",
|
|
544
|
+
}
|
|
545
|
+
)
|
|
546
|
+
|
|
547
|
+
return res
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
def build_options(
|
|
551
|
+
app: Application, existing_options: List[dict], control_objectives: List[dict]
|
|
552
|
+
) -> List[ImplementationOptionDeprecated]:
|
|
553
|
+
config = app.config
|
|
554
|
+
results = []
|
|
555
|
+
options = [
|
|
556
|
+
{
|
|
557
|
+
"Status": FULLY_IMPLEMENTED,
|
|
558
|
+
"Description": "The control is fully implemented.",
|
|
559
|
+
},
|
|
560
|
+
{"Status": NOT_IMPLEMENTED, "Description": "The control is not implemented."},
|
|
561
|
+
]
|
|
562
|
+
for obj in control_objectives:
|
|
563
|
+
for option in options:
|
|
564
|
+
if option["Status"] not in {opt["name"] for opt in existing_options if opt["objectiveId"] == obj["id"]}:
|
|
565
|
+
results.append(
|
|
566
|
+
ImplementationOptionDeprecated(
|
|
567
|
+
id=0,
|
|
568
|
+
uuid="",
|
|
569
|
+
createdById=config["userId"],
|
|
570
|
+
dateCreated=get_current_datetime(),
|
|
571
|
+
lastUpdatedById=app.config["userId"],
|
|
572
|
+
dateLastUpdated=get_current_datetime(),
|
|
573
|
+
name=option["Status"],
|
|
574
|
+
description=option["Description"],
|
|
575
|
+
archived=False,
|
|
576
|
+
securityControlId=obj["securityControlId"],
|
|
577
|
+
objectiveId=obj["id"],
|
|
578
|
+
otherId="",
|
|
579
|
+
acceptability=FULLY_IMPLEMENTED,
|
|
580
|
+
)
|
|
581
|
+
)
|
|
582
|
+
return results
|