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,922 @@
|
|
|
1
|
+
"""
|
|
2
|
+
System Characteristics are a Model Layer in the OSCAL SSP implementation model. The
|
|
3
|
+
model is documented at https://pages.nist.gov/OSCAL/concepts/layer/implementation/ssp/
|
|
4
|
+
Note that the RegScale SSP Data model collapses several NIST OSCAL model layers together
|
|
5
|
+
including Metadata, System Characteristics, and System Implementation.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
from json import JSONDecodeError
|
|
10
|
+
from typing import List, Optional, Union
|
|
11
|
+
|
|
12
|
+
from lxml.etree import Element
|
|
13
|
+
from pydantic import ValidationError
|
|
14
|
+
|
|
15
|
+
from regscale.core.app.api import Api
|
|
16
|
+
from regscale.core.app.application import Application
|
|
17
|
+
from regscale.core.app.logz import create_logger
|
|
18
|
+
from regscale.integrations.public.fedramp.reporting import log_error, log_event
|
|
19
|
+
from regscale.integrations.public.fedramp.resources import parse_backmatter
|
|
20
|
+
from regscale.integrations.public.fedramp.xml_utils import update_ssp
|
|
21
|
+
|
|
22
|
+
# flake8: noqa: C901
|
|
23
|
+
from regscale.models import SecurityPlan
|
|
24
|
+
|
|
25
|
+
logger = create_logger()
|
|
26
|
+
SYSTEM_CHARS = "System Characteristics"
|
|
27
|
+
SYSTEM_INFO = "System Information"
|
|
28
|
+
|
|
29
|
+
CAT_MAPPING = [
|
|
30
|
+
("fips-199-low", "Low"),
|
|
31
|
+
("fips-199-moderate", "Moderate"),
|
|
32
|
+
("fips-199-high", "High"),
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
LEVEL_MAPPING = [
|
|
36
|
+
("1", "Low"),
|
|
37
|
+
("2", "Moderate"),
|
|
38
|
+
("3", "High"),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
FR_AUTH_MAPPING = [
|
|
42
|
+
("fedramp-jab", "Joint Authorization Board (JAB)"),
|
|
43
|
+
("fedramp-agency", "Agency Authorization"),
|
|
44
|
+
("fedramp-li-saas", "Low Impact SaaS"),
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
STATUS_MAPPING = [
|
|
48
|
+
("operational", "Operational"),
|
|
49
|
+
("under-development", "Under Development"),
|
|
50
|
+
("under-major-modification", "Undergoing a Major Modification"),
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def get_compliance_settings_id() -> int:
|
|
55
|
+
# TODO: Move to REG-13149
|
|
56
|
+
"""
|
|
57
|
+
Return the Compliance Settings ID for FedRAMP
|
|
58
|
+
|
|
59
|
+
:return: Compliance Setting ID
|
|
60
|
+
:rtype: int
|
|
61
|
+
"""
|
|
62
|
+
from regscale.models.regscale_models.compliance_settings import ComplianceSettings
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
fedramp_comp = next(
|
|
66
|
+
comp.id for comp in ComplianceSettings.get_by_current_tenant() if comp.title == "FedRAMP Compliance Setting"
|
|
67
|
+
)
|
|
68
|
+
except (StopIteration, JSONDecodeError):
|
|
69
|
+
# Handle the case where the Compliance Setting ID is not found or the RegScale version is not compatible
|
|
70
|
+
logger.warning("Unable to find Compliance Setting ID, defaulting to 1.")
|
|
71
|
+
fedramp_comp = 1
|
|
72
|
+
return fedramp_comp
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def parse_minimum_ssp(
|
|
76
|
+
api: Api,
|
|
77
|
+
root: Element,
|
|
78
|
+
events_list: Optional[list] = None,
|
|
79
|
+
new_ssp: Optional[dict] = None,
|
|
80
|
+
ns: Optional[dict] = None,
|
|
81
|
+
) -> Union[str, int]:
|
|
82
|
+
"""The objective of this function is to parse the elements needed for an initial POST to create and return a new
|
|
83
|
+
SSP ID. The SSP ID can then be later used to update the SSP with additional information in a PUT operation, or to
|
|
84
|
+
provide the necessary ParentID for database records that require the SSP ID as a foreign key.
|
|
85
|
+
|
|
86
|
+
:param Api api: RegScale API object
|
|
87
|
+
:param Element root: lxml root Element from SSP
|
|
88
|
+
:param Optional[list] events_list: list to be populated with parsed data
|
|
89
|
+
:param Optional[dict] new_ssp: dict to be populated with parsed data
|
|
90
|
+
:param Optional[dict] ns: namespace dict
|
|
91
|
+
:return: SSP ID
|
|
92
|
+
:rtype: Union[str, int]
|
|
93
|
+
"""
|
|
94
|
+
app = Application()
|
|
95
|
+
properties_list = [] # track any properties collected during this time
|
|
96
|
+
fedrampId = root.xpath(
|
|
97
|
+
'/*/ns1:system-characteristics/ns1:system-id[@identifier-type="https://fedramp.gov"]',
|
|
98
|
+
namespaces=ns,
|
|
99
|
+
)
|
|
100
|
+
if len(fedrampId) == 0:
|
|
101
|
+
events_list.append(
|
|
102
|
+
log_error(
|
|
103
|
+
record_type="FedRAMP ID",
|
|
104
|
+
missing_element="FedRAMP ID",
|
|
105
|
+
model_layer=SYSTEM_CHARS,
|
|
106
|
+
)
|
|
107
|
+
)
|
|
108
|
+
else:
|
|
109
|
+
new_ssp["fedrampId"] = fedrampId[0].text
|
|
110
|
+
events_list.append(
|
|
111
|
+
log_event(
|
|
112
|
+
record_type="FedRAMP ID",
|
|
113
|
+
model_layer=SYSTEM_CHARS,
|
|
114
|
+
event_msg=f'Found FedRAMP-assigned identifier: {new_ssp["fedrampId"]}',
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
#
|
|
118
|
+
xpath_query = "/*/ns1:system-characteristics/ns1:system-id"
|
|
119
|
+
additional_identifiers = root.xpath(xpath_query, namespaces=ns)
|
|
120
|
+
for additional_identifier in additional_identifiers:
|
|
121
|
+
try:
|
|
122
|
+
if additional_identifier.attrib["identifier-type"] != "https://fedramp.gov":
|
|
123
|
+
property_ = {
|
|
124
|
+
"key": "identifier-type=" + additional_identifier.attrib["identifier-type"],
|
|
125
|
+
"value": additional_identifier.text,
|
|
126
|
+
"label": "Other System ID",
|
|
127
|
+
"otherAttributes": xpath_query.replace("ns1:", "{http://csrc.nist.gov/ns/oscal/1.0}"),
|
|
128
|
+
}
|
|
129
|
+
properties_list.append(property_)
|
|
130
|
+
events_list.append(
|
|
131
|
+
log_event(
|
|
132
|
+
record_type="System Identifier",
|
|
133
|
+
model_layer=SYSTEM_CHARS,
|
|
134
|
+
event_msg=f'Additional System ID detected & recorded as Property: {property_["value"]}',
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
except Exception as e:
|
|
138
|
+
logger.error(e)
|
|
139
|
+
events_list.append(
|
|
140
|
+
log_error(
|
|
141
|
+
missing_element=additional_identifier.tag,
|
|
142
|
+
record_type="Property",
|
|
143
|
+
model_layer=SYSTEM_CHARS,
|
|
144
|
+
event_msg=f"Problem importing Additional System ID {additional_identifier.text}",
|
|
145
|
+
)
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
#
|
|
149
|
+
other_identifier = root.xpath("/*/ns1:system-characteristics/ns1:system-name-short", namespaces=ns)
|
|
150
|
+
if len(other_identifier) == 0:
|
|
151
|
+
events_list.append(
|
|
152
|
+
log_error(
|
|
153
|
+
record_type=SYSTEM_INFO,
|
|
154
|
+
missing_element="System Short Name",
|
|
155
|
+
model_layer=SYSTEM_CHARS,
|
|
156
|
+
)
|
|
157
|
+
)
|
|
158
|
+
else:
|
|
159
|
+
new_ssp["otherIdentifier"] = other_identifier[0].text
|
|
160
|
+
events_list.append(
|
|
161
|
+
log_event(
|
|
162
|
+
record_type="System Short Name",
|
|
163
|
+
event_msg=f'System Short Name identified as {new_ssp["otherIdentifier"]}',
|
|
164
|
+
model_layer=SYSTEM_CHARS,
|
|
165
|
+
)
|
|
166
|
+
)
|
|
167
|
+
#
|
|
168
|
+
description = root.xpath("/*/ns1:system-characteristics/ns1:description", namespaces=ns)
|
|
169
|
+
if len(description) == 0:
|
|
170
|
+
events_list.append(
|
|
171
|
+
log_error(
|
|
172
|
+
record_type=SYSTEM_INFO,
|
|
173
|
+
missing_element="System Description",
|
|
174
|
+
model_layer=SYSTEM_CHARS,
|
|
175
|
+
)
|
|
176
|
+
)
|
|
177
|
+
else:
|
|
178
|
+
# TODO: This needs the text collapsing function that Joshua is working on.
|
|
179
|
+
# new_ssp["description"] = extract_markup_content(description[0])
|
|
180
|
+
new_ssp["description"] = ""
|
|
181
|
+
for p in description[0].findall("ns1:p", namespaces=ns):
|
|
182
|
+
new_ssp["description"] = new_ssp["description"] + p.text + " "
|
|
183
|
+
events_list.append(
|
|
184
|
+
log_event(
|
|
185
|
+
record_type=SYSTEM_INFO,
|
|
186
|
+
event_msg=f'System description recorded: {new_ssp["description"][:30]}... ',
|
|
187
|
+
model_layer=SYSTEM_CHARS,
|
|
188
|
+
)
|
|
189
|
+
)
|
|
190
|
+
#
|
|
191
|
+
fedrampAuthorizationType = root.xpath(
|
|
192
|
+
'/*/ns1:system-characteristics/ns1:prop[@name="authorization-type"][@ns="https://fedramp.gov/ns/oscal"]',
|
|
193
|
+
namespaces=ns,
|
|
194
|
+
)
|
|
195
|
+
if len(fedrampAuthorizationType) == 0:
|
|
196
|
+
events_list.append(
|
|
197
|
+
log_error(
|
|
198
|
+
record_type=SYSTEM_INFO,
|
|
199
|
+
missing_element="FedRAMP Authorization Type",
|
|
200
|
+
model_layer=SYSTEM_CHARS,
|
|
201
|
+
)
|
|
202
|
+
)
|
|
203
|
+
else:
|
|
204
|
+
new_ssp["fedrampAuthorizationType"] = apply_mapping(
|
|
205
|
+
FR_AUTH_MAPPING, fedrampAuthorizationType[0].attrib["value"]
|
|
206
|
+
)
|
|
207
|
+
events_list.append(
|
|
208
|
+
log_event(
|
|
209
|
+
record_type=SYSTEM_INFO,
|
|
210
|
+
event_msg=f'FedRAMP Authorization Type: {new_ssp["fedrampAuthorizationType"]}',
|
|
211
|
+
model_layer=SYSTEM_CHARS,
|
|
212
|
+
)
|
|
213
|
+
)
|
|
214
|
+
#
|
|
215
|
+
authenticationLevel = root.xpath(
|
|
216
|
+
'/*/ns1:system-characteristics/ns1:prop[@name="security-eauth-level"][@class="security-eauth"]',
|
|
217
|
+
namespaces=ns,
|
|
218
|
+
)
|
|
219
|
+
if len(authenticationLevel) == 0:
|
|
220
|
+
events_list.append(
|
|
221
|
+
log_error(
|
|
222
|
+
record_type=SYSTEM_INFO,
|
|
223
|
+
missing_element="FedRAMP Authentication Level",
|
|
224
|
+
model_layer=SYSTEM_CHARS,
|
|
225
|
+
)
|
|
226
|
+
)
|
|
227
|
+
else:
|
|
228
|
+
new_ssp["authenticationLevel"] = apply_mapping(LEVEL_MAPPING, authenticationLevel[0].attrib["value"])
|
|
229
|
+
events_list.append(
|
|
230
|
+
log_event(
|
|
231
|
+
record_type=SYSTEM_INFO,
|
|
232
|
+
event_msg=f'FedRAMP Authentication Level: {new_ssp["authenticationLevel"]}',
|
|
233
|
+
model_layer=SYSTEM_CHARS,
|
|
234
|
+
)
|
|
235
|
+
)
|
|
236
|
+
#
|
|
237
|
+
identityAssuranceLevel = root.xpath(
|
|
238
|
+
'/*/ns1:system-characteristics/ns1:prop[@name="identity-assurance-level"]/@value',
|
|
239
|
+
namespaces=ns,
|
|
240
|
+
)
|
|
241
|
+
if len(identityAssuranceLevel) == 0:
|
|
242
|
+
events_list.append(
|
|
243
|
+
log_error(
|
|
244
|
+
record_type=SYSTEM_INFO,
|
|
245
|
+
missing_element="FedRAMP Identity Assurance Level",
|
|
246
|
+
model_layer=SYSTEM_CHARS,
|
|
247
|
+
)
|
|
248
|
+
)
|
|
249
|
+
else:
|
|
250
|
+
new_ssp["identityAssuranceLevel"] = apply_mapping(LEVEL_MAPPING, identityAssuranceLevel[0])
|
|
251
|
+
events_list.append(
|
|
252
|
+
log_event(
|
|
253
|
+
record_type=SYSTEM_INFO,
|
|
254
|
+
event_msg=f'FedRAMP Identity Assurance Level: {new_ssp["identityAssuranceLevel"]}',
|
|
255
|
+
model_layer=SYSTEM_CHARS,
|
|
256
|
+
)
|
|
257
|
+
)
|
|
258
|
+
#
|
|
259
|
+
authenticatorAssuranceLevel = root.xpath(
|
|
260
|
+
'/*/ns1:system-characteristics/ns1:prop[@name="authenticator-assurance-level"]/@value',
|
|
261
|
+
namespaces=ns,
|
|
262
|
+
)
|
|
263
|
+
if len(authenticatorAssuranceLevel) == 0:
|
|
264
|
+
events_list.append(
|
|
265
|
+
log_error(
|
|
266
|
+
record_type=SYSTEM_INFO,
|
|
267
|
+
missing_element="FedRAMP Authenticator Assurance Level",
|
|
268
|
+
model_layer=SYSTEM_CHARS,
|
|
269
|
+
)
|
|
270
|
+
)
|
|
271
|
+
else:
|
|
272
|
+
new_ssp["authenticatorAssuranceLevel"] = apply_mapping(LEVEL_MAPPING, identityAssuranceLevel[0])
|
|
273
|
+
events_list.append(
|
|
274
|
+
log_event(
|
|
275
|
+
record_type=SYSTEM_INFO,
|
|
276
|
+
event_msg=f'FedRAMP Authenticator Assurance Level: {new_ssp["authenticatorAssuranceLevel"]}',
|
|
277
|
+
model_layer=SYSTEM_CHARS,
|
|
278
|
+
)
|
|
279
|
+
)
|
|
280
|
+
#
|
|
281
|
+
federationAssuranceLevel = root.xpath(
|
|
282
|
+
'/*/ns1:system-characteristics/ns1:prop[@name="federation-assurance-level"]/@value',
|
|
283
|
+
namespaces=ns,
|
|
284
|
+
)
|
|
285
|
+
if len(federationAssuranceLevel) == 0:
|
|
286
|
+
events_list.append(
|
|
287
|
+
log_error(
|
|
288
|
+
record_type=SYSTEM_INFO,
|
|
289
|
+
missing_element="FedRAMP Federation Assurance Level",
|
|
290
|
+
model_layer=SYSTEM_CHARS,
|
|
291
|
+
)
|
|
292
|
+
)
|
|
293
|
+
else:
|
|
294
|
+
new_ssp["federationAssuranceLevel"] = apply_mapping(LEVEL_MAPPING, federationAssuranceLevel[0])
|
|
295
|
+
events_list.append(
|
|
296
|
+
log_event(
|
|
297
|
+
record_type=SYSTEM_INFO,
|
|
298
|
+
event_msg=f'FedRAMP Federation Assurance Level: {new_ssp["federationAssuranceLevel"]}',
|
|
299
|
+
model_layer=SYSTEM_CHARS,
|
|
300
|
+
)
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
#
|
|
304
|
+
system_name = root.xpath("/*/ns1:system-characteristics/ns1:system-name", namespaces=ns)
|
|
305
|
+
if len(system_name) == 0:
|
|
306
|
+
events_list.append(
|
|
307
|
+
log_error(
|
|
308
|
+
record_type=SYSTEM_INFO,
|
|
309
|
+
missing_element="System Name",
|
|
310
|
+
model_layer=SYSTEM_CHARS,
|
|
311
|
+
)
|
|
312
|
+
)
|
|
313
|
+
new_ssp["systemName"] = "Cloud Service Provider System" # FAILSAFE W/ DUMMY DATA FOR REQUIRED VALUES
|
|
314
|
+
else:
|
|
315
|
+
new_ssp["systemName"] = system_name[0].text
|
|
316
|
+
events_list.append(
|
|
317
|
+
log_event(
|
|
318
|
+
record_type="System Name",
|
|
319
|
+
event_msg=f'System Name identified as {new_ssp["systemName"]}',
|
|
320
|
+
model_layer=SYSTEM_CHARS,
|
|
321
|
+
)
|
|
322
|
+
)
|
|
323
|
+
#
|
|
324
|
+
new_ssp["confidentiality"] = "Low" # default value
|
|
325
|
+
confidentiality = root.xpath(
|
|
326
|
+
"/*/ns1:system-characteristics/ns1:security-impact-level/ns1:security-objective-confidentiality",
|
|
327
|
+
namespaces=ns,
|
|
328
|
+
)
|
|
329
|
+
if len(confidentiality) == 0:
|
|
330
|
+
events_list.append(
|
|
331
|
+
log_error(
|
|
332
|
+
record_type=SYSTEM_INFO,
|
|
333
|
+
missing_element="Security Objective (Confidentiality) ",
|
|
334
|
+
model_layer=SYSTEM_CHARS,
|
|
335
|
+
)
|
|
336
|
+
)
|
|
337
|
+
else:
|
|
338
|
+
new_ssp["confidentiality"] = apply_mapping(CAT_MAPPING, confidentiality[0].text)
|
|
339
|
+
events_list.append(
|
|
340
|
+
log_event(
|
|
341
|
+
record_type=SYSTEM_INFO,
|
|
342
|
+
event_msg=f'Recorded System Security Confidentiality: {new_ssp["confidentiality"]}',
|
|
343
|
+
model_layer=SYSTEM_CHARS,
|
|
344
|
+
)
|
|
345
|
+
)
|
|
346
|
+
#
|
|
347
|
+
new_ssp["integrity"] = "Low" # default value
|
|
348
|
+
integrity = root.xpath(
|
|
349
|
+
"/*/ns1:system-characteristics/ns1:security-impact-level/ns1:security-objective-integrity",
|
|
350
|
+
namespaces=ns,
|
|
351
|
+
)
|
|
352
|
+
if len(integrity) == 0:
|
|
353
|
+
events_list.append(
|
|
354
|
+
log_error(
|
|
355
|
+
record_type=SYSTEM_INFO,
|
|
356
|
+
missing_element="Security Objective (Integrity) ",
|
|
357
|
+
model_layer=SYSTEM_CHARS,
|
|
358
|
+
)
|
|
359
|
+
)
|
|
360
|
+
else:
|
|
361
|
+
new_ssp["integrity"] = apply_mapping(CAT_MAPPING, integrity[0].text)
|
|
362
|
+
events_list.append(
|
|
363
|
+
log_event(
|
|
364
|
+
record_type=SYSTEM_INFO,
|
|
365
|
+
event_msg=f'Recorded System Security Integrity: {new_ssp["integrity"]}',
|
|
366
|
+
model_layer=SYSTEM_CHARS,
|
|
367
|
+
)
|
|
368
|
+
)
|
|
369
|
+
#
|
|
370
|
+
new_ssp["availability"] = "Low" # default value
|
|
371
|
+
availability = root.xpath(
|
|
372
|
+
"/*/ns1:system-characteristics/ns1:security-impact-level/ns1:security-objective-availability",
|
|
373
|
+
namespaces=ns,
|
|
374
|
+
)
|
|
375
|
+
if len(availability) == 0:
|
|
376
|
+
events_list.append(
|
|
377
|
+
log_error(
|
|
378
|
+
record_type=SYSTEM_INFO,
|
|
379
|
+
missing_element="Security Objective (Availability) ",
|
|
380
|
+
model_layer=SYSTEM_CHARS,
|
|
381
|
+
)
|
|
382
|
+
)
|
|
383
|
+
else:
|
|
384
|
+
new_ssp["availability"] = apply_mapping(CAT_MAPPING, availability[0].text)
|
|
385
|
+
events_list.append(
|
|
386
|
+
log_event(
|
|
387
|
+
record_type=SYSTEM_INFO,
|
|
388
|
+
event_msg=f'Recorded System Security Availability: {new_ssp["availability"]}',
|
|
389
|
+
model_layer=SYSTEM_CHARS,
|
|
390
|
+
)
|
|
391
|
+
)
|
|
392
|
+
#
|
|
393
|
+
new_ssp["overallCategorization"] = "Low" # default value
|
|
394
|
+
overall_categorization = root.xpath("/*/ns1:system-characteristics/ns1:security-sensitivity-level", namespaces=ns)
|
|
395
|
+
if len(overall_categorization) == 0:
|
|
396
|
+
events_list.append(
|
|
397
|
+
log_error(
|
|
398
|
+
record_type=SYSTEM_INFO,
|
|
399
|
+
missing_element="Security Objective (Overall Categorization) ",
|
|
400
|
+
model_layer=SYSTEM_CHARS,
|
|
401
|
+
)
|
|
402
|
+
)
|
|
403
|
+
else:
|
|
404
|
+
new_ssp["overallCategorization"] = apply_mapping(CAT_MAPPING, overall_categorization[0].text)
|
|
405
|
+
events_list.append(
|
|
406
|
+
log_event(
|
|
407
|
+
record_type=SYSTEM_INFO,
|
|
408
|
+
event_msg=f'Recorded System Security Overall Categorization: {new_ssp["overallCategorization"]}',
|
|
409
|
+
model_layer=SYSTEM_CHARS,
|
|
410
|
+
)
|
|
411
|
+
)
|
|
412
|
+
#
|
|
413
|
+
new_ssp["status"] = "Operational" # default value
|
|
414
|
+
status = root.xpath("/*/ns1:system-characteristics/ns1:status", namespaces=ns)
|
|
415
|
+
if len(status) == 0:
|
|
416
|
+
events_list.append(
|
|
417
|
+
log_error(
|
|
418
|
+
record_type=SYSTEM_INFO,
|
|
419
|
+
missing_element="System Operating Status",
|
|
420
|
+
model_layer=SYSTEM_CHARS,
|
|
421
|
+
)
|
|
422
|
+
)
|
|
423
|
+
else:
|
|
424
|
+
new_ssp["status"] = apply_mapping(STATUS_MAPPING, status[0].attrib["state"])
|
|
425
|
+
events_list.append(
|
|
426
|
+
log_event(
|
|
427
|
+
record_type=SYSTEM_INFO,
|
|
428
|
+
event_msg=f'System Operating status detected: {new_ssp["status"]}',
|
|
429
|
+
model_layer=SYSTEM_CHARS,
|
|
430
|
+
)
|
|
431
|
+
)
|
|
432
|
+
status_remarks = root.xpath("/*/ns1:system-characteristics/ns1:status/ns1:remarks", namespaces=ns)
|
|
433
|
+
if len(status_remarks) > 0:
|
|
434
|
+
new_ssp["explanationForNonOperational"] = ""
|
|
435
|
+
for p in status_remarks[0].findall("ns1:p", namespaces=ns):
|
|
436
|
+
new_ssp["explanationForNonOperational"] = new_ssp["explanationForNonOperational"] + p.text + " "
|
|
437
|
+
#
|
|
438
|
+
# CLOUD SERVICE MODELS
|
|
439
|
+
new_ssp["bModelSaaS"] = root.xpath(
|
|
440
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:prop[@name='cloud-service-model'][@value='saas']",
|
|
441
|
+
namespaces=ns,
|
|
442
|
+
)
|
|
443
|
+
if len(new_ssp["bModelSaaS"]) == 0:
|
|
444
|
+
new_ssp["bModelSaaS"] = False
|
|
445
|
+
else:
|
|
446
|
+
new_ssp["bModelSaaS"] = True
|
|
447
|
+
#
|
|
448
|
+
new_ssp["bModelPaaS"] = root.xpath(
|
|
449
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:prop[@name='cloud-service-model'][@value='paas']",
|
|
450
|
+
namespaces=ns,
|
|
451
|
+
)
|
|
452
|
+
if len(new_ssp["bModelPaaS"]) == 0:
|
|
453
|
+
new_ssp["bModelPaaS"] = False
|
|
454
|
+
else:
|
|
455
|
+
new_ssp["bModelPaaS"] = True
|
|
456
|
+
#
|
|
457
|
+
new_ssp["bModelIaaS"] = root.xpath(
|
|
458
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:prop[@name='cloud-service-model'][@value='iaas']",
|
|
459
|
+
namespaces=ns,
|
|
460
|
+
)
|
|
461
|
+
if len(new_ssp["bModelIaaS"]) == 0:
|
|
462
|
+
new_ssp["bModelIaaS"] = False
|
|
463
|
+
else:
|
|
464
|
+
new_ssp["bModelIaaS"] = True
|
|
465
|
+
#
|
|
466
|
+
new_ssp["bModelOther"] = root.xpath(
|
|
467
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:prop[@name='cloud-service-model'][@value='other']",
|
|
468
|
+
namespaces=ns,
|
|
469
|
+
)
|
|
470
|
+
if len(new_ssp["bModelOther"]) == 0:
|
|
471
|
+
new_ssp["bModelOther"] = False
|
|
472
|
+
else:
|
|
473
|
+
new_ssp["bModelOther"] = True
|
|
474
|
+
#
|
|
475
|
+
remarks = root.xpath(
|
|
476
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:prop[@name='cloud-service-model'][@value='other']/ns1:remarks",
|
|
477
|
+
namespaces=ns,
|
|
478
|
+
)
|
|
479
|
+
if len(remarks) == 0:
|
|
480
|
+
pass
|
|
481
|
+
else:
|
|
482
|
+
new_ssp["OtherModelRemarks"] = ""
|
|
483
|
+
for p in remarks[0].findall("ns1:p", namespaces=ns):
|
|
484
|
+
new_ssp["OtherModelRemarks"] = new_ssp["OtherModelRemarks"] + p.text + " "
|
|
485
|
+
|
|
486
|
+
# CLOUD DEPLOYMENTS
|
|
487
|
+
|
|
488
|
+
new_ssp["bDeployPublic"] = root.xpath(
|
|
489
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:prop[@name='cloud-deployment-model'][@value='public-cloud']",
|
|
490
|
+
namespaces=ns,
|
|
491
|
+
)
|
|
492
|
+
if len(new_ssp["bDeployPublic"]) == 0:
|
|
493
|
+
new_ssp["bDeployPublic"] = False
|
|
494
|
+
else:
|
|
495
|
+
new_ssp["bDeployPublic"] = True
|
|
496
|
+
#
|
|
497
|
+
new_ssp["bDeployPrivate"] = root.xpath(
|
|
498
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:prop[@name='cloud-deployment-model'][@value='private-cloud']",
|
|
499
|
+
namespaces=ns,
|
|
500
|
+
)
|
|
501
|
+
if len(new_ssp["bDeployPrivate"]) == 0:
|
|
502
|
+
new_ssp["bDeployPrivate"] = False
|
|
503
|
+
else:
|
|
504
|
+
new_ssp["bDeployPrivate"] = True
|
|
505
|
+
#
|
|
506
|
+
new_ssp["bDeployGov"] = root.xpath(
|
|
507
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:prop[@name='cloud-deployment-model'][@value='government-only-cloud']",
|
|
508
|
+
namespaces=ns,
|
|
509
|
+
)
|
|
510
|
+
if len(new_ssp["bDeployGov"]) == 0:
|
|
511
|
+
new_ssp["bDeployGov"] = False
|
|
512
|
+
else:
|
|
513
|
+
new_ssp["bDeployGov"] = True
|
|
514
|
+
#
|
|
515
|
+
new_ssp["bDeployHybrid"] = root.xpath(
|
|
516
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:prop[@name='cloud-deployment-model'][@value='hybrid-cloud']",
|
|
517
|
+
namespaces=ns,
|
|
518
|
+
)
|
|
519
|
+
if len(new_ssp["bDeployHybrid"]) == 0:
|
|
520
|
+
new_ssp["bDeployHybrid"] = False
|
|
521
|
+
else:
|
|
522
|
+
new_ssp["bDeployHybrid"] = True
|
|
523
|
+
#
|
|
524
|
+
new_ssp["bDeployOther"] = root.xpath(
|
|
525
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:prop[@name='cloud-deployment-model'][@value='other-cloud']",
|
|
526
|
+
namespaces=ns,
|
|
527
|
+
)
|
|
528
|
+
if len(new_ssp["bDeployOther"]) == 0:
|
|
529
|
+
new_ssp["bDeployOther"] = False
|
|
530
|
+
else:
|
|
531
|
+
new_ssp["bDeployOther"] = True
|
|
532
|
+
#
|
|
533
|
+
remarks = root.xpath(
|
|
534
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:prop[@name='cloud-service-model'][@value='other']/ns1:remarks",
|
|
535
|
+
namespaces=ns,
|
|
536
|
+
)
|
|
537
|
+
if len(remarks) == 0:
|
|
538
|
+
pass
|
|
539
|
+
else:
|
|
540
|
+
new_ssp["DeployOtherRemarks"] = ""
|
|
541
|
+
for p in remarks[0].findall("ns1:p", namespaces=ns):
|
|
542
|
+
new_ssp["DeployOtherRemarks"] = new_ssp["DeployOtherRemarks"] + p.text + " "
|
|
543
|
+
# TODO: This RegScale value doesn't seem to have a FedRAMP counterpart. Confirm w/ Travis or Dale
|
|
544
|
+
new_ssp["systemType"] = "Major Application"
|
|
545
|
+
new_ssp["systemOwnerId"] = app.config["userId"]
|
|
546
|
+
from regscale.utils.version import RegscaleVersion
|
|
547
|
+
from packaging.version import Version
|
|
548
|
+
|
|
549
|
+
regscale_version = RegscaleVersion.get_platform_version()
|
|
550
|
+
if len(regscale_version) >= 10 or Version(regscale_version) >= Version("6.13.0.0"):
|
|
551
|
+
new_ssp["complianceSettingsId"] = get_compliance_settings_id()
|
|
552
|
+
ssp_id = post_SSP(api, new_ssp)
|
|
553
|
+
return ssp_id
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
def parse_system_characteristics(
|
|
557
|
+
ssp_id: Union[int, str], root: Element, events_list: Optional[list] = None, ns: Optional[dict] = None
|
|
558
|
+
):
|
|
559
|
+
"""Parse system characteristics from OSCAL SSP XML to RegScale SSP JSON
|
|
560
|
+
|
|
561
|
+
:param Union[int, str] ssp_id: The ID of the SSP to be updated
|
|
562
|
+
:param Element root: lxml root Element from SSP
|
|
563
|
+
:param Optional[list] events_list: list to be populated with parsed data, defaults to None
|
|
564
|
+
:param Optional[dict] ns: namespace dict, defaults to None
|
|
565
|
+
"""
|
|
566
|
+
|
|
567
|
+
ssp_updates = {} # store any key value pairs to update SSP with
|
|
568
|
+
|
|
569
|
+
# Information / Classification Types
|
|
570
|
+
information_types = root.xpath(
|
|
571
|
+
"/*/ns1:system-characteristics/ns1:system-information/ns1:information-type",
|
|
572
|
+
namespaces=ns,
|
|
573
|
+
)
|
|
574
|
+
if len(information_types) == 0:
|
|
575
|
+
events_list.append(
|
|
576
|
+
log_error(
|
|
577
|
+
record_type="Information Types",
|
|
578
|
+
missing_element="At least one Information Type",
|
|
579
|
+
model_layer=SYSTEM_CHARS,
|
|
580
|
+
)
|
|
581
|
+
)
|
|
582
|
+
else:
|
|
583
|
+
parse_classificationType(information_types, ns, events_list, ssp_id)
|
|
584
|
+
|
|
585
|
+
# Privacy Impact Assessment
|
|
586
|
+
# TODO: Doesn't seem to be a RegScale counterpart for <prop name="privacy-sensitive" value="yes"/> - confirm w/ SME
|
|
587
|
+
parse_privacy(root=root, ns=ns, events_list=events_list, ssp_id=ssp_id)
|
|
588
|
+
|
|
589
|
+
# SYSTEM DESCRIPTION
|
|
590
|
+
authorizationBoundary = root.xpath(
|
|
591
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:authorization-boundary/ns1:description",
|
|
592
|
+
namespaces=ns,
|
|
593
|
+
)
|
|
594
|
+
if len(authorizationBoundary) > 0:
|
|
595
|
+
ssp_updates["authorizationBoundary"] = ""
|
|
596
|
+
for p in authorizationBoundary[0].findall("ns1:p", namespaces=ns):
|
|
597
|
+
if p.text:
|
|
598
|
+
ssp_updates["authorizationBoundary"] = ssp_updates["authorizationBoundary"] + p.text + " "
|
|
599
|
+
events_list.append(
|
|
600
|
+
log_event(
|
|
601
|
+
model_layer=SYSTEM_CHARS,
|
|
602
|
+
record_type=SYSTEM_INFO,
|
|
603
|
+
event_msg="Authorization Boundary recorded.",
|
|
604
|
+
)
|
|
605
|
+
)
|
|
606
|
+
else:
|
|
607
|
+
events_list.append(
|
|
608
|
+
log_error(
|
|
609
|
+
model_layer=SYSTEM_CHARS,
|
|
610
|
+
record_type=SYSTEM_INFO,
|
|
611
|
+
missing_element="Auth. Boundary Description",
|
|
612
|
+
)
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
# check if there is back-matter
|
|
616
|
+
if back_matter := root.find(".//ns1:back-matter", namespaces=ns):
|
|
617
|
+
# get the resources
|
|
618
|
+
resources = back_matter.findall(".//ns1:resource", namespaces=ns)
|
|
619
|
+
results = parse_backmatter(
|
|
620
|
+
resource_elem=resources,
|
|
621
|
+
back_matter=back_matter,
|
|
622
|
+
root=root,
|
|
623
|
+
ns=ns,
|
|
624
|
+
ssp_id=ssp_id,
|
|
625
|
+
events_list=events_list,
|
|
626
|
+
)
|
|
627
|
+
event_msg = (
|
|
628
|
+
f"Created {results['linksCreated']} new link(s), created "
|
|
629
|
+
f"{results['referencesCreated']} reference(s), and uploaded "
|
|
630
|
+
f"{results['filesUploaded']} file(s) in RegScale."
|
|
631
|
+
)
|
|
632
|
+
events_list.append(
|
|
633
|
+
log_event(
|
|
634
|
+
record_type="Back Matter",
|
|
635
|
+
event_msg=event_msg,
|
|
636
|
+
model_layer="Back Matter",
|
|
637
|
+
)
|
|
638
|
+
)
|
|
639
|
+
else:
|
|
640
|
+
events_list.append(
|
|
641
|
+
log_error(
|
|
642
|
+
model_layer=SYSTEM_CHARS,
|
|
643
|
+
record_type=SYSTEM_INFO,
|
|
644
|
+
missing_element="back-matter",
|
|
645
|
+
)
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
network_architecture = (
|
|
649
|
+
root.xpath(
|
|
650
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:network-architecture/ns1:description",
|
|
651
|
+
namespaces=ns,
|
|
652
|
+
)
|
|
653
|
+
or []
|
|
654
|
+
)
|
|
655
|
+
|
|
656
|
+
if len(network_architecture) > 0:
|
|
657
|
+
ssp_updates["networkArchitecture"] = ""
|
|
658
|
+
for p in network_architecture[0].findall("ns1:p", namespaces=ns):
|
|
659
|
+
if p.text:
|
|
660
|
+
ssp_updates["networkArchitecture"] = ssp_updates["networkArchitecture"] + p.text + " "
|
|
661
|
+
events_list.append(
|
|
662
|
+
log_event(
|
|
663
|
+
model_layer=SYSTEM_CHARS,
|
|
664
|
+
record_type=SYSTEM_INFO,
|
|
665
|
+
event_msg="Network Architecture description recorded.",
|
|
666
|
+
)
|
|
667
|
+
)
|
|
668
|
+
else:
|
|
669
|
+
events_list.append(
|
|
670
|
+
log_error(
|
|
671
|
+
model_layer=SYSTEM_CHARS,
|
|
672
|
+
record_type=SYSTEM_INFO,
|
|
673
|
+
missing_element="Network Architecture",
|
|
674
|
+
)
|
|
675
|
+
)
|
|
676
|
+
#
|
|
677
|
+
dataFlow = root.xpath(
|
|
678
|
+
"/ns1:system-security-plan/ns1:system-characteristics/ns1:data-flow/ns1:description",
|
|
679
|
+
namespaces=ns,
|
|
680
|
+
)
|
|
681
|
+
if len(dataFlow) > 0:
|
|
682
|
+
ssp_updates["dataFlow"] = ""
|
|
683
|
+
for p in dataFlow[0].findall("ns1:p", namespaces=ns):
|
|
684
|
+
if p.text:
|
|
685
|
+
ssp_updates["dataFlow"] = ssp_updates["dataFlow"] + p.text + " "
|
|
686
|
+
events_list.append(
|
|
687
|
+
log_event(
|
|
688
|
+
model_layer=SYSTEM_CHARS,
|
|
689
|
+
record_type=SYSTEM_INFO,
|
|
690
|
+
event_msg="Data Flow description recorded.",
|
|
691
|
+
)
|
|
692
|
+
)
|
|
693
|
+
else:
|
|
694
|
+
events_list.append(
|
|
695
|
+
log_error(
|
|
696
|
+
model_layer=SYSTEM_CHARS,
|
|
697
|
+
record_type=SYSTEM_INFO,
|
|
698
|
+
missing_element="Data Flow",
|
|
699
|
+
)
|
|
700
|
+
)
|
|
701
|
+
|
|
702
|
+
update_ssp(ssp_updates, ssp_id)
|
|
703
|
+
|
|
704
|
+
# properties such as authorization type will be mapped to regscale counterparts, where applicable, but will also be
|
|
705
|
+
# stored as properties for consistency in export.
|
|
706
|
+
# if Export team needs these NOT to be recorded in properties. that can be arranged. Export could just choose
|
|
707
|
+
# to check if a property already exists before adding it, however, which would avoid potential for duplication on export
|
|
708
|
+
"""
|
|
709
|
+
else: # if none of these other condit`ions are met, store as a custom property
|
|
710
|
+
ancestry = ''
|
|
711
|
+
for parent in prop.parents:
|
|
712
|
+
ancestry = ancestry + '/' + parent.name
|
|
713
|
+
property_ = {}
|
|
714
|
+
property_['key'] = prop.attrs['name']
|
|
715
|
+
property_['value'] = prop.attrs['value']
|
|
716
|
+
property_['label'] = 'Custom Property'
|
|
717
|
+
property_['otherAttributes'] = ancestry + str(prop)
|
|
718
|
+
properties_list.append(property_)
|
|
719
|
+
"""
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
def apply_mapping(mapping: List[tuple], value: str) -> str:
|
|
723
|
+
"""
|
|
724
|
+
Apply a mapping to a value
|
|
725
|
+
|
|
726
|
+
:param List[tuple] mapping: List of mapping pair tuples - (original,new)
|
|
727
|
+
:param str value: Thing to be mapped to a new value
|
|
728
|
+
:return: New value
|
|
729
|
+
:rtype: str
|
|
730
|
+
"""
|
|
731
|
+
for original, new in mapping:
|
|
732
|
+
if value == original:
|
|
733
|
+
value = new
|
|
734
|
+
break
|
|
735
|
+
return value
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
def post_SSP(api: Api, new_ssp: dict):
|
|
739
|
+
"""Create the initial SSP"""
|
|
740
|
+
app = Application()
|
|
741
|
+
headers_json = {
|
|
742
|
+
"accept": "*/*",
|
|
743
|
+
"Content-Type": "application/json-patch+json",
|
|
744
|
+
"Authorization": app.config["token"],
|
|
745
|
+
}
|
|
746
|
+
# If data is incomplete This fails w/ 500 error ( which means the json string being received by the server is either malformed or missing something
|
|
747
|
+
logger.info("Uploading SSP to RegScale...")
|
|
748
|
+
try:
|
|
749
|
+
ssp = SecurityPlan(**new_ssp)
|
|
750
|
+
except ValidationError as exc:
|
|
751
|
+
logger.error(f"Failed to validate: {exc}")
|
|
752
|
+
return "artifacts/import-results.csv", {
|
|
753
|
+
"status": "failed",
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
if new_ssp := ssp.create():
|
|
757
|
+
new_ssp_id = new_ssp.id
|
|
758
|
+
else:
|
|
759
|
+
new_ssp_id = None
|
|
760
|
+
logger.debug(new_ssp_id)
|
|
761
|
+
|
|
762
|
+
if not new_ssp_id:
|
|
763
|
+
# This generally succeeds if the ssp failed to pass pydantic check for required values in securityplans module
|
|
764
|
+
logger.warning("Some required data may have failed to be imported. Trying to upload SSP with incomplete data ")
|
|
765
|
+
import json
|
|
766
|
+
|
|
767
|
+
dat = {}
|
|
768
|
+
response = api.post(
|
|
769
|
+
url=app.config["domain"] + "/api/securityplans",
|
|
770
|
+
json=new_ssp,
|
|
771
|
+
)
|
|
772
|
+
logger.debug(response.status_code)
|
|
773
|
+
if not response.raise_for_status():
|
|
774
|
+
dat = response.json()
|
|
775
|
+
if "id" in dat:
|
|
776
|
+
new_ssp_id = dat["id"]
|
|
777
|
+
|
|
778
|
+
return new_ssp_id
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
def parse_classificationType(information_types, ns, events_list, ssp_id):
|
|
782
|
+
"""Information Types in FedRAMP language correspond to Classification Types in RegScale, and are stored in the
|
|
783
|
+
ClassificationTypes table. . Classification/Information Types are created in the 'Setup' portion of the RegScale app
|
|
784
|
+
& at the Tenant level. Classification/Information types are then associated with an individual SSP through the
|
|
785
|
+
'Subsystems' menu. The mapping between a Classification/Information type and the SSP is stored in the
|
|
786
|
+
ClassifiedRecords database table."""
|
|
787
|
+
|
|
788
|
+
# TODO: There currently isn't capability to track the base vs selected & adjustment reason, or categ. system
|
|
789
|
+
for information_type in information_types:
|
|
790
|
+
classificationType_dict = {}
|
|
791
|
+
classificationType_dict["uuid"] = information_type.attrib["uuid"]
|
|
792
|
+
# start with default values to avoid breaking on import
|
|
793
|
+
classificationType_dict["title"] = "Name of Information Type"
|
|
794
|
+
classificationType_dict["description"] = ""
|
|
795
|
+
classificationType_dict["confidentiality"] = "Low"
|
|
796
|
+
classificationType_dict["integrity"] = "Low"
|
|
797
|
+
classificationType_dict["availability"] = "Low"
|
|
798
|
+
if information_type.find("ns1:title", namespaces=ns) is not None:
|
|
799
|
+
classificationType_dict["title"] = information_type.find("ns1:title", namespaces=ns).text
|
|
800
|
+
if information_type.find("ns1:description", namespaces=ns) is not None:
|
|
801
|
+
for p in information_type.find("ns1:description", namespaces=ns).findall("ns1:p", namespaces=ns):
|
|
802
|
+
classificationType_dict["description"] = classificationType_dict["description"] + p.text + " "
|
|
803
|
+
if information_type.find("ns1:confidentiality-impact/ns1:selected", namespaces=ns) is not None:
|
|
804
|
+
classificationType_dict["confidentiality"] = apply_mapping(
|
|
805
|
+
CAT_MAPPING,
|
|
806
|
+
information_type.find("ns1:confidentiality-impact/ns1:selected", namespaces=ns).text,
|
|
807
|
+
)
|
|
808
|
+
if information_type.find("ns1:integrity-impact/ns1:selected", namespaces=ns) is not None:
|
|
809
|
+
classificationType_dict["integrity"] = apply_mapping(
|
|
810
|
+
CAT_MAPPING,
|
|
811
|
+
information_type.find("ns1:integrity-impact/ns1:selected", namespaces=ns).text,
|
|
812
|
+
)
|
|
813
|
+
if information_type.find("ns1:availability-impact/ns1:selected", namespaces=ns) is not None:
|
|
814
|
+
classificationType_dict["availability"] = apply_mapping(
|
|
815
|
+
CAT_MAPPING,
|
|
816
|
+
information_type.find("ns1:availability-impact/ns1:selected", namespaces=ns).text,
|
|
817
|
+
)
|
|
818
|
+
classification_type_id = upload_classificationType(classificationType_dict, ssp_id)
|
|
819
|
+
if classification_type_id:
|
|
820
|
+
events_list.append(
|
|
821
|
+
log_event(
|
|
822
|
+
record_type="Information Type",
|
|
823
|
+
model_layer=SYSTEM_CHARS,
|
|
824
|
+
event_msg=f'Recorded Information Type for: {classificationType_dict["title"]}',
|
|
825
|
+
)
|
|
826
|
+
)
|
|
827
|
+
else:
|
|
828
|
+
events_list.append(
|
|
829
|
+
log_error(
|
|
830
|
+
record_type="Information Type",
|
|
831
|
+
model_layer=SYSTEM_CHARS,
|
|
832
|
+
missing_element="Information Type",
|
|
833
|
+
event_msg='Failed to post Information Type for {classificationType_dict["title"]}.',
|
|
834
|
+
)
|
|
835
|
+
)
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
def upload_classificationType(classificationType_dict, ssp_id):
|
|
839
|
+
app = Application()
|
|
840
|
+
api = Api()
|
|
841
|
+
headers_json = {
|
|
842
|
+
"accept": "*/*",
|
|
843
|
+
"Content-Type": "application/json-patch+json",
|
|
844
|
+
"Authorization": app.config["token"],
|
|
845
|
+
}
|
|
846
|
+
ssp_classification = json.dumps(classificationType_dict)
|
|
847
|
+
response = api.post(
|
|
848
|
+
url=app.config["domain"] + "/api/classificationTypes",
|
|
849
|
+
data=ssp_classification,
|
|
850
|
+
headers=headers_json,
|
|
851
|
+
)
|
|
852
|
+
if response.status_code == 200: # If successfully upload classification type, then add mapping to SSP
|
|
853
|
+
classifiedRecords_entry = {}
|
|
854
|
+
classifiedRecords_entry["classificationTypeId"] = json.loads(response.content)["id"]
|
|
855
|
+
classifiedRecords_entry["parentRecordId"] = ssp_id
|
|
856
|
+
classifiedRecords_entry["parentModule"] = "securityplans"
|
|
857
|
+
classifiedRecord_json = json.dumps(classifiedRecords_entry)
|
|
858
|
+
response = api.post(
|
|
859
|
+
url=app.config["domain"] + "/api/classifiedRecords",
|
|
860
|
+
data=classifiedRecord_json,
|
|
861
|
+
headers=headers_json,
|
|
862
|
+
)
|
|
863
|
+
if response.status_code == 200:
|
|
864
|
+
return "Success"
|
|
865
|
+
else:
|
|
866
|
+
return None
|
|
867
|
+
else:
|
|
868
|
+
return None
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
def parse_privacy(root, events_list, ns, ssp_id):
|
|
872
|
+
"Privacy Impact Assessment pertains to the Privacy tab of RegScale Application and the Privacy database table."
|
|
873
|
+
try:
|
|
874
|
+
privacyImpactAssessment = {}
|
|
875
|
+
privacyImpactAssessment["piiCollection"] = root.xpath(
|
|
876
|
+
'/*/ns1:system-characteristics/ns1:system-information/ns1:prop[@name="pta-1"][@ns="https://fedramp.gov/ns/oscal"]/@value',
|
|
877
|
+
namespaces=ns,
|
|
878
|
+
)[0].capitalize()
|
|
879
|
+
privacyImpactAssessment["piiPublicCollection"] = root.xpath(
|
|
880
|
+
'/*/ns1:system-characteristics/ns1:system-information/ns1:prop[@name="pta-2"][@ns="https://fedramp.gov/ns/oscal"]/@value',
|
|
881
|
+
namespaces=ns,
|
|
882
|
+
)[0].capitalize()
|
|
883
|
+
privacyImpactAssessment["piaConducted"] = root.xpath(
|
|
884
|
+
'/*/ns1:system-characteristics/ns1:system-information/ns1:prop[@name="pta-3"][@ns="https://fedramp.gov/ns/oscal"]/@value',
|
|
885
|
+
namespaces=ns,
|
|
886
|
+
)[0].capitalize()
|
|
887
|
+
privacyImpactAssessment["privacyActSystem"] = root.xpath(
|
|
888
|
+
'/*/ns1:system-characteristics/ns1:system-information/ns1:prop[@name="pta-4"][@ns="https://fedramp.gov/ns/oscal"]/@value',
|
|
889
|
+
namespaces=ns,
|
|
890
|
+
)[0].capitalize()
|
|
891
|
+
privacyImpactAssessment["sornExists"] = root.xpath(
|
|
892
|
+
'/*/ns1:system-characteristics/ns1:system-information/ns1:prop[@name="pta-4"][@ns="https://fedramp.gov/ns/oscal"]/@value',
|
|
893
|
+
namespaces=ns,
|
|
894
|
+
)[0].capitalize()
|
|
895
|
+
privacyImpactAssessment["sornId"] = root.xpath(
|
|
896
|
+
'/*/ns1:system-characteristics/ns1:system-information/ns1:prop[@name="sorn-id"][@ns="https://fedramp.gov/ns/oscal"]/@value',
|
|
897
|
+
namespaces=ns,
|
|
898
|
+
)[0].capitalize()
|
|
899
|
+
privacyImpactAssessment["SecurityPlanId"] = ssp_id
|
|
900
|
+
privacyImpactAssessment["isPublic"] = True
|
|
901
|
+
# Will have to come back to this. Requires linking to the Privacy officer / information officer contacts per
|
|
902
|
+
# application layer logic, if any of the privacy questions are "yes".
|
|
903
|
+
"""
|
|
904
|
+
response_id = post_privacy(privacyImpactAssessment)
|
|
905
|
+
if response_id:
|
|
906
|
+
events_list.append(log_event(model_layer='System Characteristics', record_type='Privacy Impact Assessment',
|
|
907
|
+
event_msg='Successfully imported PTA/PIA data.'))
|
|
908
|
+
else:
|
|
909
|
+
events_list.append(log_error(model_layer='System Characteristics', record_type='Privacy Assessment',
|
|
910
|
+
missing_element='Privacy Assessment',
|
|
911
|
+
event_msg='Problem extracting or uploading PTA/PIA data.'))
|
|
912
|
+
"""
|
|
913
|
+
except Exception as e:
|
|
914
|
+
logger.warning(e)
|
|
915
|
+
events_list.append(
|
|
916
|
+
log_error(
|
|
917
|
+
model_layer=SYSTEM_CHARS,
|
|
918
|
+
record_type="Privacy Assessment",
|
|
919
|
+
missing_element="Privacy Assessment",
|
|
920
|
+
event_msg="Problem extracting PTA/PIA data.",
|
|
921
|
+
)
|
|
922
|
+
)
|