regscale-cli 6.21.2.0__py3-none-any.whl → 6.28.2.1__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.
- regscale/_version.py +1 -1
- regscale/airflow/hierarchy.py +2 -2
- regscale/core/app/api.py +5 -2
- regscale/core/app/application.py +36 -6
- regscale/core/app/internal/control_editor.py +73 -21
- regscale/core/app/internal/evidence.py +727 -204
- regscale/core/app/internal/login.py +4 -2
- regscale/core/app/internal/model_editor.py +219 -64
- regscale/core/app/utils/app_utils.py +86 -12
- regscale/core/app/utils/catalog_utils/common.py +1 -1
- regscale/core/login.py +21 -4
- regscale/core/utils/async_graphql_client.py +363 -0
- regscale/core/utils/date.py +77 -1
- regscale/dev/cli.py +26 -0
- regscale/dev/code_gen.py +109 -24
- regscale/dev/version.py +72 -0
- regscale/integrations/commercial/__init__.py +30 -2
- regscale/integrations/commercial/aws/audit_manager_compliance.py +3908 -0
- regscale/integrations/commercial/aws/cli.py +3107 -54
- regscale/integrations/commercial/aws/cloudtrail_control_mappings.py +333 -0
- regscale/integrations/commercial/aws/cloudtrail_evidence.py +501 -0
- regscale/integrations/commercial/aws/cloudwatch_control_mappings.py +357 -0
- regscale/integrations/commercial/aws/cloudwatch_evidence.py +490 -0
- regscale/integrations/commercial/{amazon → aws}/common.py +71 -19
- regscale/integrations/commercial/aws/config_compliance.py +914 -0
- regscale/integrations/commercial/aws/conformance_pack_mappings.py +198 -0
- regscale/integrations/commercial/aws/control_compliance_analyzer.py +439 -0
- regscale/integrations/commercial/aws/evidence_generator.py +283 -0
- regscale/integrations/commercial/aws/guardduty_control_mappings.py +340 -0
- regscale/integrations/commercial/aws/guardduty_evidence.py +1053 -0
- regscale/integrations/commercial/aws/iam_control_mappings.py +368 -0
- regscale/integrations/commercial/aws/iam_evidence.py +574 -0
- regscale/integrations/commercial/aws/inventory/__init__.py +338 -22
- regscale/integrations/commercial/aws/inventory/base.py +107 -5
- regscale/integrations/commercial/aws/inventory/resources/analytics.py +390 -0
- regscale/integrations/commercial/aws/inventory/resources/applications.py +234 -0
- regscale/integrations/commercial/aws/inventory/resources/audit_manager.py +513 -0
- regscale/integrations/commercial/aws/inventory/resources/cloudtrail.py +315 -0
- regscale/integrations/commercial/aws/inventory/resources/cloudtrail_logs_metadata.py +476 -0
- regscale/integrations/commercial/aws/inventory/resources/cloudwatch.py +191 -0
- regscale/integrations/commercial/aws/inventory/resources/compute.py +328 -9
- regscale/integrations/commercial/aws/inventory/resources/config.py +464 -0
- regscale/integrations/commercial/aws/inventory/resources/containers.py +74 -9
- regscale/integrations/commercial/aws/inventory/resources/database.py +481 -31
- regscale/integrations/commercial/aws/inventory/resources/developer_tools.py +253 -0
- regscale/integrations/commercial/aws/inventory/resources/guardduty.py +286 -0
- regscale/integrations/commercial/aws/inventory/resources/iam.py +470 -0
- regscale/integrations/commercial/aws/inventory/resources/inspector.py +476 -0
- regscale/integrations/commercial/aws/inventory/resources/integration.py +175 -61
- regscale/integrations/commercial/aws/inventory/resources/kms.py +447 -0
- regscale/integrations/commercial/aws/inventory/resources/machine_learning.py +358 -0
- regscale/integrations/commercial/aws/inventory/resources/networking.py +390 -67
- regscale/integrations/commercial/aws/inventory/resources/s3.py +394 -0
- regscale/integrations/commercial/aws/inventory/resources/security.py +268 -72
- regscale/integrations/commercial/aws/inventory/resources/securityhub.py +473 -0
- regscale/integrations/commercial/aws/inventory/resources/storage.py +288 -29
- regscale/integrations/commercial/aws/inventory/resources/systems_manager.py +657 -0
- regscale/integrations/commercial/aws/inventory/resources/vpc.py +655 -0
- regscale/integrations/commercial/aws/kms_control_mappings.py +288 -0
- regscale/integrations/commercial/aws/kms_evidence.py +879 -0
- regscale/integrations/commercial/aws/ocsf/__init__.py +7 -0
- regscale/integrations/commercial/aws/ocsf/constants.py +115 -0
- regscale/integrations/commercial/aws/ocsf/mapper.py +435 -0
- regscale/integrations/commercial/aws/org_control_mappings.py +286 -0
- regscale/integrations/commercial/aws/org_evidence.py +666 -0
- regscale/integrations/commercial/aws/s3_control_mappings.py +356 -0
- regscale/integrations/commercial/aws/s3_evidence.py +632 -0
- regscale/integrations/commercial/aws/scanner.py +1072 -205
- regscale/integrations/commercial/aws/security_hub.py +319 -0
- regscale/integrations/commercial/aws/session_manager.py +282 -0
- regscale/integrations/commercial/aws/ssm_control_mappings.py +291 -0
- regscale/integrations/commercial/aws/ssm_evidence.py +492 -0
- regscale/integrations/commercial/jira.py +489 -153
- regscale/integrations/commercial/microsoft_defender/defender.py +326 -5
- regscale/integrations/commercial/microsoft_defender/defender_api.py +348 -14
- regscale/integrations/commercial/microsoft_defender/defender_constants.py +157 -0
- regscale/integrations/commercial/qualys/__init__.py +167 -68
- regscale/integrations/commercial/qualys/scanner.py +305 -39
- regscale/integrations/commercial/sarif/sairf_importer.py +432 -0
- regscale/integrations/commercial/sarif/sarif_converter.py +67 -0
- regscale/integrations/commercial/sicura/api.py +79 -42
- regscale/integrations/commercial/sicura/commands.py +8 -2
- regscale/integrations/commercial/sicura/scanner.py +83 -44
- regscale/integrations/commercial/stigv2/ckl_parser.py +5 -5
- regscale/integrations/commercial/synqly/assets.py +133 -16
- regscale/integrations/commercial/synqly/edr.py +2 -8
- regscale/integrations/commercial/synqly/query_builder.py +536 -0
- regscale/integrations/commercial/synqly/ticketing.py +27 -0
- regscale/integrations/commercial/synqly/vulnerabilities.py +165 -28
- regscale/integrations/commercial/tenablev2/cis_parsers.py +453 -0
- regscale/integrations/commercial/tenablev2/cis_scanner.py +447 -0
- regscale/integrations/commercial/tenablev2/commands.py +146 -5
- regscale/integrations/commercial/tenablev2/scanner.py +1 -3
- regscale/integrations/commercial/tenablev2/stig_parsers.py +113 -57
- regscale/integrations/commercial/wizv2/WizDataMixin.py +1 -1
- regscale/integrations/commercial/wizv2/click.py +191 -76
- regscale/integrations/commercial/wizv2/compliance/__init__.py +15 -0
- regscale/integrations/commercial/wizv2/{policy_compliance_helpers.py → compliance/helpers.py} +78 -60
- regscale/integrations/commercial/wizv2/compliance_report.py +1592 -0
- regscale/integrations/commercial/wizv2/core/__init__.py +133 -0
- regscale/integrations/commercial/wizv2/{async_client.py → core/client.py} +7 -3
- regscale/integrations/commercial/wizv2/{constants.py → core/constants.py} +92 -89
- regscale/integrations/commercial/wizv2/core/file_operations.py +237 -0
- regscale/integrations/commercial/wizv2/fetchers/__init__.py +11 -0
- regscale/integrations/commercial/wizv2/{data_fetcher.py → fetchers/policy_assessment.py} +66 -9
- regscale/integrations/commercial/wizv2/file_cleanup.py +104 -0
- regscale/integrations/commercial/wizv2/issue.py +776 -28
- regscale/integrations/commercial/wizv2/models/__init__.py +0 -0
- regscale/integrations/commercial/wizv2/parsers/__init__.py +34 -0
- regscale/integrations/commercial/wizv2/{parsers.py → parsers/main.py} +1 -1
- regscale/integrations/commercial/wizv2/processors/__init__.py +11 -0
- regscale/integrations/commercial/wizv2/{finding_processor.py → processors/finding.py} +1 -1
- regscale/integrations/commercial/wizv2/reports.py +243 -0
- regscale/integrations/commercial/wizv2/sbom.py +1 -1
- regscale/integrations/commercial/wizv2/scanner.py +1031 -441
- regscale/integrations/commercial/wizv2/utils/__init__.py +48 -0
- regscale/integrations/commercial/wizv2/{utils.py → utils/main.py} +116 -61
- regscale/integrations/commercial/wizv2/variables.py +89 -3
- regscale/integrations/compliance_integration.py +1036 -151
- regscale/integrations/control_matcher.py +432 -0
- regscale/integrations/due_date_handler.py +333 -0
- regscale/integrations/milestone_manager.py +291 -0
- regscale/integrations/public/__init__.py +14 -0
- regscale/integrations/public/cci_importer.py +834 -0
- regscale/integrations/public/csam/__init__.py +0 -0
- regscale/integrations/public/csam/csam.py +938 -0
- regscale/integrations/public/csam/csam_agency_defined.py +179 -0
- regscale/integrations/public/csam/csam_common.py +154 -0
- regscale/integrations/public/csam/csam_controls.py +432 -0
- regscale/integrations/public/csam/csam_poam.py +124 -0
- regscale/integrations/public/fedramp/click.py +77 -6
- regscale/integrations/public/fedramp/docx_parser.py +10 -1
- regscale/integrations/public/fedramp/fedramp_cis_crm.py +675 -289
- regscale/integrations/public/fedramp/fedramp_five.py +1 -1
- regscale/integrations/public/fedramp/poam/scanner.py +75 -7
- regscale/integrations/public/fedramp/poam_export_v5.py +888 -0
- regscale/integrations/scanner_integration.py +1961 -430
- regscale/models/integration_models/CCI_List.xml +1 -0
- regscale/models/integration_models/aqua.py +2 -2
- regscale/models/integration_models/cisa_kev_data.json +805 -11
- regscale/models/integration_models/flat_file_importer/__init__.py +5 -8
- regscale/models/integration_models/nexpose.py +36 -10
- regscale/models/integration_models/qualys.py +3 -4
- regscale/models/integration_models/synqly_models/capabilities.json +1 -1
- regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +87 -18
- regscale/models/integration_models/synqly_models/filter_parser.py +332 -0
- regscale/models/integration_models/synqly_models/ocsf_mapper.py +124 -25
- regscale/models/integration_models/synqly_models/synqly_model.py +89 -16
- regscale/models/locking.py +12 -8
- regscale/models/platform.py +4 -2
- regscale/models/regscale_models/__init__.py +7 -0
- regscale/models/regscale_models/assessment.py +2 -1
- regscale/models/regscale_models/catalog.py +1 -1
- regscale/models/regscale_models/compliance_settings.py +251 -1
- regscale/models/regscale_models/component.py +1 -0
- regscale/models/regscale_models/control_implementation.py +236 -41
- regscale/models/regscale_models/control_objective.py +74 -5
- regscale/models/regscale_models/file.py +2 -0
- regscale/models/regscale_models/form_field_value.py +5 -3
- regscale/models/regscale_models/inheritance.py +44 -0
- regscale/models/regscale_models/issue.py +301 -102
- regscale/models/regscale_models/milestone.py +33 -14
- regscale/models/regscale_models/organization.py +3 -0
- regscale/models/regscale_models/regscale_model.py +310 -73
- regscale/models/regscale_models/security_plan.py +4 -2
- regscale/models/regscale_models/vulnerability.py +3 -3
- regscale/regscale.py +25 -4
- regscale/templates/__init__.py +0 -0
- regscale/utils/threading/threadhandler.py +20 -15
- regscale/validation/record.py +23 -1
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/METADATA +17 -33
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/RECORD +310 -111
- tests/core/__init__.py +0 -0
- tests/core/utils/__init__.py +0 -0
- tests/core/utils/test_async_graphql_client.py +472 -0
- tests/fixtures/test_fixture.py +13 -8
- tests/regscale/core/test_login.py +171 -4
- tests/regscale/integrations/commercial/__init__.py +0 -0
- tests/regscale/integrations/commercial/aws/__init__.py +0 -0
- tests/regscale/integrations/commercial/aws/test_audit_manager_compliance.py +1304 -0
- tests/regscale/integrations/commercial/aws/test_audit_manager_evidence_aggregation.py +341 -0
- tests/regscale/integrations/commercial/aws/test_aws_analytics_collector.py +260 -0
- tests/regscale/integrations/commercial/aws/test_aws_applications_collector.py +242 -0
- tests/regscale/integrations/commercial/aws/test_aws_audit_manager_collector.py +1155 -0
- tests/regscale/integrations/commercial/aws/test_aws_cloudtrail_collector.py +534 -0
- tests/regscale/integrations/commercial/aws/test_aws_config_collector.py +400 -0
- tests/regscale/integrations/commercial/aws/test_aws_developer_tools_collector.py +203 -0
- tests/regscale/integrations/commercial/aws/test_aws_guardduty_collector.py +315 -0
- tests/regscale/integrations/commercial/aws/test_aws_iam_collector.py +458 -0
- tests/regscale/integrations/commercial/aws/test_aws_inspector_collector.py +353 -0
- tests/regscale/integrations/commercial/aws/test_aws_inventory_integration.py +530 -0
- tests/regscale/integrations/commercial/aws/test_aws_kms_collector.py +919 -0
- tests/regscale/integrations/commercial/aws/test_aws_machine_learning_collector.py +237 -0
- tests/regscale/integrations/commercial/aws/test_aws_s3_collector.py +722 -0
- tests/regscale/integrations/commercial/aws/test_aws_scanner_integration.py +722 -0
- tests/regscale/integrations/commercial/aws/test_aws_securityhub_collector.py +792 -0
- tests/regscale/integrations/commercial/aws/test_aws_systems_manager_collector.py +918 -0
- tests/regscale/integrations/commercial/aws/test_aws_vpc_collector.py +996 -0
- tests/regscale/integrations/commercial/aws/test_cli_evidence.py +431 -0
- tests/regscale/integrations/commercial/aws/test_cloudtrail_control_mappings.py +452 -0
- tests/regscale/integrations/commercial/aws/test_cloudtrail_evidence.py +788 -0
- tests/regscale/integrations/commercial/aws/test_config_compliance.py +298 -0
- tests/regscale/integrations/commercial/aws/test_conformance_pack_mappings.py +200 -0
- tests/regscale/integrations/commercial/aws/test_control_compliance_analyzer.py +375 -0
- tests/regscale/integrations/commercial/aws/test_datetime_parsing.py +223 -0
- tests/regscale/integrations/commercial/aws/test_evidence_generator.py +386 -0
- tests/regscale/integrations/commercial/aws/test_guardduty_control_mappings.py +564 -0
- tests/regscale/integrations/commercial/aws/test_guardduty_evidence.py +1041 -0
- tests/regscale/integrations/commercial/aws/test_iam_control_mappings.py +718 -0
- tests/regscale/integrations/commercial/aws/test_iam_evidence.py +1375 -0
- tests/regscale/integrations/commercial/aws/test_kms_control_mappings.py +656 -0
- tests/regscale/integrations/commercial/aws/test_kms_evidence.py +1163 -0
- tests/regscale/integrations/commercial/aws/test_ocsf_mapper.py +370 -0
- tests/regscale/integrations/commercial/aws/test_org_control_mappings.py +546 -0
- tests/regscale/integrations/commercial/aws/test_org_evidence.py +1240 -0
- tests/regscale/integrations/commercial/aws/test_s3_control_mappings.py +672 -0
- tests/regscale/integrations/commercial/aws/test_s3_evidence.py +987 -0
- tests/regscale/integrations/commercial/aws/test_scanner_evidence.py +373 -0
- tests/regscale/integrations/commercial/aws/test_security_hub_config_filtering.py +539 -0
- tests/regscale/integrations/commercial/aws/test_session_manager.py +516 -0
- tests/regscale/integrations/commercial/aws/test_ssm_control_mappings.py +588 -0
- tests/regscale/integrations/commercial/aws/test_ssm_evidence.py +735 -0
- tests/regscale/integrations/commercial/conftest.py +28 -0
- tests/regscale/integrations/commercial/microsoft_defender/__init__.py +1 -0
- tests/regscale/integrations/commercial/microsoft_defender/test_defender.py +1517 -0
- tests/regscale/integrations/commercial/microsoft_defender/test_defender_api.py +1748 -0
- tests/regscale/integrations/commercial/microsoft_defender/test_defender_constants.py +327 -0
- tests/regscale/integrations/commercial/microsoft_defender/test_defender_scanner.py +487 -0
- tests/regscale/integrations/commercial/test_aws.py +3742 -0
- tests/regscale/integrations/commercial/test_burp.py +48 -0
- tests/regscale/integrations/commercial/test_crowdstrike.py +49 -0
- tests/regscale/integrations/commercial/test_dependabot.py +341 -0
- tests/regscale/integrations/commercial/test_gcp.py +1543 -0
- tests/regscale/integrations/commercial/test_gitlab.py +549 -0
- tests/regscale/integrations/commercial/test_ip_mac_address_length.py +84 -0
- tests/regscale/integrations/commercial/test_jira.py +2204 -0
- tests/regscale/integrations/commercial/test_npm_audit.py +42 -0
- tests/regscale/integrations/commercial/test_okta.py +1228 -0
- tests/regscale/integrations/commercial/test_sarif_converter.py +251 -0
- tests/regscale/integrations/commercial/test_sicura.py +349 -0
- tests/regscale/integrations/commercial/test_snow.py +423 -0
- tests/regscale/integrations/commercial/test_sonarcloud.py +394 -0
- tests/regscale/integrations/commercial/test_sqlserver.py +186 -0
- tests/regscale/integrations/commercial/test_stig.py +33 -0
- tests/regscale/integrations/commercial/test_stig_mapper.py +153 -0
- tests/regscale/integrations/commercial/test_stigv2.py +406 -0
- tests/regscale/integrations/commercial/test_wiz.py +1365 -0
- tests/regscale/integrations/commercial/test_wiz_inventory.py +256 -0
- tests/regscale/integrations/commercial/wizv2/__init__.py +339 -0
- tests/regscale/integrations/commercial/wizv2/compliance/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/compliance/test_helpers.py +903 -0
- tests/regscale/integrations/commercial/wizv2/core/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/core/test_auth.py +701 -0
- tests/regscale/integrations/commercial/wizv2/core/test_client.py +1037 -0
- tests/regscale/integrations/commercial/wizv2/core/test_file_operations.py +989 -0
- tests/regscale/integrations/commercial/wizv2/fetchers/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/fetchers/test_policy_assessment.py +805 -0
- tests/regscale/integrations/commercial/wizv2/parsers/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/parsers/test_main.py +1153 -0
- tests/regscale/integrations/commercial/wizv2/processors/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/processors/test_finding.py +671 -0
- tests/regscale/integrations/commercial/wizv2/test_WizDataMixin.py +537 -0
- tests/regscale/integrations/commercial/wizv2/test_click_comprehensive.py +851 -0
- tests/regscale/integrations/commercial/wizv2/test_compliance_report_comprehensive.py +910 -0
- tests/regscale/integrations/commercial/wizv2/test_compliance_report_normalization.py +138 -0
- tests/regscale/integrations/commercial/wizv2/test_file_cleanup.py +283 -0
- tests/regscale/integrations/commercial/wizv2/test_file_operations.py +260 -0
- tests/regscale/integrations/commercial/wizv2/test_issue.py +343 -0
- tests/regscale/integrations/commercial/wizv2/test_issue_comprehensive.py +1203 -0
- tests/regscale/integrations/commercial/wizv2/test_reports.py +497 -0
- tests/regscale/integrations/commercial/wizv2/test_sbom.py +643 -0
- tests/regscale/integrations/commercial/wizv2/test_scanner_comprehensive.py +805 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_click_client_id.py +165 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_compliance_report.py +1394 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_compliance_unit.py +341 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_control_normalization.py +138 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_findings_comprehensive.py +364 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_inventory_comprehensive.py +644 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_status_mapping.py +149 -0
- tests/regscale/integrations/commercial/wizv2/test_wizv2.py +1218 -0
- tests/regscale/integrations/commercial/wizv2/test_wizv2_utils.py +519 -0
- tests/regscale/integrations/commercial/wizv2/utils/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/utils/test_main.py +1523 -0
- tests/regscale/integrations/public/__init__.py +0 -0
- tests/regscale/integrations/public/fedramp/__init__.py +1 -0
- tests/regscale/integrations/public/fedramp/test_gen_asset_list.py +150 -0
- tests/regscale/integrations/public/fedramp/test_poam_export_v5.py +1293 -0
- tests/regscale/integrations/public/test_alienvault.py +220 -0
- tests/regscale/integrations/public/test_cci.py +1053 -0
- tests/regscale/integrations/public/test_cisa.py +1021 -0
- tests/regscale/integrations/public/test_emass.py +518 -0
- tests/regscale/integrations/public/test_fedramp.py +1152 -0
- tests/regscale/integrations/public/test_fedramp_cis_crm.py +3661 -0
- tests/regscale/integrations/public/test_file_uploads.py +506 -0
- tests/regscale/integrations/public/test_oscal.py +453 -0
- tests/regscale/integrations/test_compliance_status_mapping.py +406 -0
- tests/regscale/integrations/test_control_matcher.py +1421 -0
- tests/regscale/integrations/test_control_matching.py +155 -0
- tests/regscale/integrations/test_milestone_manager.py +408 -0
- tests/regscale/models/test_control_implementation.py +118 -3
- tests/regscale/models/test_form_field_value_integration.py +304 -0
- tests/regscale/models/test_issue.py +378 -1
- tests/regscale/models/test_module_integration.py +582 -0
- tests/regscale/models/test_tenable_integrations.py +811 -105
- regscale/integrations/commercial/wizv2/policy_compliance.py +0 -3057
- regscale/integrations/public/fedramp/mappings/fedramp_r4_parts.json +0 -7388
- regscale/integrations/public/fedramp/mappings/fedramp_r5_parts.json +0 -9605
- regscale/integrations/public/fedramp/parts_mapper.py +0 -107
- /regscale/integrations/commercial/{amazon → sarif}/__init__.py +0 -0
- /regscale/integrations/commercial/wizv2/{wiz_auth.py → core/auth.py} +0 -0
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/LICENSE +0 -0
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/WHEEL +0 -0
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/entry_points.txt +0 -0
- {regscale_cli-6.21.2.0.dist-info → regscale_cli-6.28.2.1.dist-info}/top_level.txt +0 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
"""RegScale Microsoft Defender recommendations and alerts integration"""
|
|
4
4
|
# standard python imports
|
|
5
|
+
|
|
5
6
|
import logging
|
|
6
7
|
from datetime import datetime, timedelta
|
|
7
8
|
from os import PathLike
|
|
@@ -10,6 +11,7 @@ from typing import Literal, Optional, Tuple, Union
|
|
|
10
11
|
|
|
11
12
|
import click
|
|
12
13
|
from rich.console import Console
|
|
14
|
+
from rich.table import Table
|
|
13
15
|
|
|
14
16
|
from regscale.core.app.api import Api
|
|
15
17
|
from regscale.core.app.internal.login import is_valid
|
|
@@ -24,6 +26,7 @@ from regscale.core.app.utils.app_utils import (
|
|
|
24
26
|
uncamel_case,
|
|
25
27
|
)
|
|
26
28
|
from regscale.integrations.commercial.microsoft_defender.defender_api import DefenderApi
|
|
29
|
+
from regscale.integrations.commercial.microsoft_defender.defender_constants import EVIDENCE_TO_CONTROLS_MAPPING
|
|
27
30
|
from regscale.models import File, Issue, regscale_id, regscale_module, ssp_or_component_id
|
|
28
31
|
from regscale.models.app_models.click import NotRequiredIf
|
|
29
32
|
from regscale.models.integration_models.defender_data import DefenderData
|
|
@@ -68,12 +71,12 @@ def defender():
|
|
|
68
71
|
@defender.command(name="authenticate")
|
|
69
72
|
@click.option(
|
|
70
73
|
"--system",
|
|
71
|
-
type=click.Choice(["cloud", "365"], case_sensitive=False),
|
|
72
|
-
help="Pull recommendations from Microsoft Defender 365
|
|
74
|
+
type=click.Choice(["cloud", "365", "entra"], case_sensitive=False),
|
|
75
|
+
help="Pull recommendations from Microsoft Defender 365, Microsoft Defender for Cloud, or Azure Entra.",
|
|
73
76
|
prompt="Please choose a system",
|
|
74
77
|
required=True,
|
|
75
78
|
)
|
|
76
|
-
def authenticate_in_defender(system: Literal["cloud", "365"]):
|
|
79
|
+
def authenticate_in_defender(system: Literal["cloud", "365", "entra"]):
|
|
77
80
|
"""Obtains an access token using the credentials provided in init.yaml."""
|
|
78
81
|
authenticate(system=system)
|
|
79
82
|
|
|
@@ -225,6 +228,85 @@ def import_alerts(
|
|
|
225
228
|
)
|
|
226
229
|
|
|
227
230
|
|
|
231
|
+
@defender.command(name="collect_entra_evidence")
|
|
232
|
+
@ssp_or_component_id()
|
|
233
|
+
@click.option(
|
|
234
|
+
"--days_back",
|
|
235
|
+
"-d",
|
|
236
|
+
type=click.INT,
|
|
237
|
+
help="Number of days back to collect audit logs",
|
|
238
|
+
default=30,
|
|
239
|
+
)
|
|
240
|
+
@click.option(
|
|
241
|
+
"--evidence_type",
|
|
242
|
+
"-t",
|
|
243
|
+
type=click.Choice(
|
|
244
|
+
["all", "users_groups", "rbac_pim", "conditional_access", "authentication", "audit_logs", "access_reviews"],
|
|
245
|
+
case_sensitive=False,
|
|
246
|
+
),
|
|
247
|
+
help="Type of evidence to collect",
|
|
248
|
+
default="all",
|
|
249
|
+
)
|
|
250
|
+
def collect_entra_evidence(regscale_ssp_id: int, component_id: int, days_back: int, evidence_type: str):
|
|
251
|
+
"""
|
|
252
|
+
Collect Azure Entra evidence for FedRAMP compliance controls and upload to RegScale
|
|
253
|
+
"""
|
|
254
|
+
# Validate parent module for evidence collection
|
|
255
|
+
from regscale.validation.record import validate_component_or_ssp
|
|
256
|
+
|
|
257
|
+
validate_component_or_ssp(ssp_id=regscale_ssp_id, component_id=component_id)
|
|
258
|
+
parent_id = regscale_ssp_id or component_id
|
|
259
|
+
parent_module = "securityplans" if regscale_ssp_id else "components"
|
|
260
|
+
|
|
261
|
+
collect_and_upload_entra_evidence(
|
|
262
|
+
parent_id=parent_id, parent_module=parent_module, days_back=days_back, evidence_type=evidence_type
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@defender.command(name="show_entra_mappings")
|
|
267
|
+
@click.option(
|
|
268
|
+
"--evidence_type",
|
|
269
|
+
"-t",
|
|
270
|
+
type=click.Choice(
|
|
271
|
+
["all", "users_groups", "rbac_pim", "conditional_access", "authentication", "audit_logs", "access_reviews"],
|
|
272
|
+
case_sensitive=False,
|
|
273
|
+
),
|
|
274
|
+
help="Show mappings for specific evidence type",
|
|
275
|
+
default="all",
|
|
276
|
+
)
|
|
277
|
+
def show_entra_mappings(evidence_type: str):
|
|
278
|
+
"""
|
|
279
|
+
Show which FedRAMP controls are mapped to each Azure Entra evidence type
|
|
280
|
+
"""
|
|
281
|
+
if evidence_type == "all":
|
|
282
|
+
evidence_types_to_show = EVIDENCE_TO_CONTROLS_MAPPING.keys()
|
|
283
|
+
else:
|
|
284
|
+
# Map category to specific evidence types
|
|
285
|
+
category_to_evidence = {
|
|
286
|
+
"users_groups": ["users", "guest_users", "security_groups"],
|
|
287
|
+
"rbac_pim": ["role_assignments", "role_definitions", "pim_assignments", "pim_eligibility"],
|
|
288
|
+
"conditional_access": ["conditional_access"],
|
|
289
|
+
"authentication": ["auth_methods_policy", "user_mfa_registration", "mfa_registered_users"],
|
|
290
|
+
"audit_logs": ["sign_in_logs", "directory_audits", "provisioning_logs"],
|
|
291
|
+
"access_reviews": ["access_review_definitions"],
|
|
292
|
+
}
|
|
293
|
+
evidence_types_to_show = category_to_evidence.get(evidence_type, [evidence_type])
|
|
294
|
+
# create a table using rich and add a row for each evidence type
|
|
295
|
+
table = Table(title="Azure Entra Evidence to FedRAMP Controls Mapping", show_lines=True)
|
|
296
|
+
table.add_column("Evidence Type", style="#10c4d3")
|
|
297
|
+
table.add_column("Controls", style="#18a8e9")
|
|
298
|
+
table.add_column("Total Controls", style="#ff9d20")
|
|
299
|
+
for evidence_key in evidence_types_to_show:
|
|
300
|
+
if evidence_key in EVIDENCE_TO_CONTROLS_MAPPING:
|
|
301
|
+
controls = EVIDENCE_TO_CONTROLS_MAPPING[evidence_key]
|
|
302
|
+
table.add_row(evidence_key.replace("_", " ").title(), ", ".join(controls), str(len(controls)))
|
|
303
|
+
console.print(table)
|
|
304
|
+
|
|
305
|
+
console.print(
|
|
306
|
+
"[dim]Use 'regscale defender collect_entra_evidence' to collect and upload evidence to these controls[/dim]"
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
|
|
228
310
|
def import_defender_alerts(
|
|
229
311
|
folder_path: PathLike[str],
|
|
230
312
|
regscale_ssp_id: int,
|
|
@@ -268,11 +350,11 @@ def import_defender_alerts(
|
|
|
268
350
|
)
|
|
269
351
|
|
|
270
352
|
|
|
271
|
-
def authenticate(system: Literal["cloud", "365"]) -> None:
|
|
353
|
+
def authenticate(system: Literal["cloud", "365", "entra"]) -> None:
|
|
272
354
|
"""
|
|
273
355
|
Obtains an access token using the credentials provided in init.yaml
|
|
274
356
|
|
|
275
|
-
:param Literal["cloud", "365"] system: The system to authenticate for, either Defender 365
|
|
357
|
+
:param Literal["cloud", "365", "entra"] system: The system to authenticate for, either Defender 365, Defender for Cloud, or Azure Entra
|
|
276
358
|
:rtype: None
|
|
277
359
|
"""
|
|
278
360
|
_ = check_license()
|
|
@@ -947,3 +1029,242 @@ def fetch_save_and_upload_query(
|
|
|
947
1029
|
api=defender_api.api,
|
|
948
1030
|
):
|
|
949
1031
|
logger.info(f"Successfully uploaded {file_path.name} to {parent_module} #{parent_id} in RegScale.")
|
|
1032
|
+
|
|
1033
|
+
|
|
1034
|
+
def collect_and_upload_entra_evidence(
|
|
1035
|
+
parent_id: int, parent_module: str, days_back: int = 30, evidence_type: str = "all"
|
|
1036
|
+
) -> None:
|
|
1037
|
+
"""
|
|
1038
|
+
Collect Azure Entra evidence for FedRAMP compliance controls and upload to RegScale
|
|
1039
|
+
|
|
1040
|
+
:param int parent_id: The RegScale ID to upload evidence to
|
|
1041
|
+
:param str parent_module: The RegScale module to upload evidence to
|
|
1042
|
+
:param int days_back: Number of days back to collect audit logs
|
|
1043
|
+
:param str evidence_type: Type of evidence to collect
|
|
1044
|
+
:rtype: None
|
|
1045
|
+
"""
|
|
1046
|
+
app = check_license()
|
|
1047
|
+
api = Api()
|
|
1048
|
+
|
|
1049
|
+
if not is_valid(app=app):
|
|
1050
|
+
error_and_exit(LOGIN_ERROR)
|
|
1051
|
+
|
|
1052
|
+
logger.info(f"Starting Azure Entra evidence collection for {evidence_type}...")
|
|
1053
|
+
|
|
1054
|
+
defender_api = DefenderApi(system="entra")
|
|
1055
|
+
|
|
1056
|
+
try:
|
|
1057
|
+
if evidence_type == "all":
|
|
1058
|
+
evidence_data = defender_api.collect_all_entra_evidence(days_back=days_back)
|
|
1059
|
+
else:
|
|
1060
|
+
evidence_data = collect_specific_evidence_type(defender_api, evidence_type, days_back)
|
|
1061
|
+
|
|
1062
|
+
upload_evidence_files(evidence_data, parent_id, parent_module, api, evidence_type)
|
|
1063
|
+
|
|
1064
|
+
except Exception as e:
|
|
1065
|
+
error_and_exit(f"Error collecting Azure Entra evidence: {e}")
|
|
1066
|
+
|
|
1067
|
+
|
|
1068
|
+
def collect_specific_evidence_type(
|
|
1069
|
+
defender_api: DefenderApi, evidence_type: str, days_back: int
|
|
1070
|
+
) -> dict[str, list[Path]]:
|
|
1071
|
+
"""
|
|
1072
|
+
Collect specific type of Azure Entra evidence
|
|
1073
|
+
|
|
1074
|
+
:param DefenderApi defender_api: The Defender API instance
|
|
1075
|
+
:param str evidence_type: Type of evidence to collect
|
|
1076
|
+
:param int days_back: Number of days back for audit logs
|
|
1077
|
+
:return: Dictionary containing evidence data and file paths to saved csv evidence files
|
|
1078
|
+
:rtype: dict[str, list[Path]]
|
|
1079
|
+
"""
|
|
1080
|
+
evidence_data = {}
|
|
1081
|
+
start_date = (datetime.now() - timedelta(days=days_back)).strftime("%Y-%m-%dT00:00:00Z")
|
|
1082
|
+
|
|
1083
|
+
if evidence_type == "users_groups":
|
|
1084
|
+
evidence_data["users"] = defender_api.get_and_save_entra_evidence("users")
|
|
1085
|
+
evidence_data["guest_users"] = defender_api.get_and_save_entra_evidence("guest_users")
|
|
1086
|
+
evidence_data["groups_and_members"] = defender_api.get_and_save_entra_evidence("groups_and_members")
|
|
1087
|
+
evidence_data["security_groups"] = defender_api.get_and_save_entra_evidence("security_groups")
|
|
1088
|
+
|
|
1089
|
+
elif evidence_type == "rbac_pim":
|
|
1090
|
+
evidence_data["role_assignments"] = defender_api.get_and_save_entra_evidence("role_assignments")
|
|
1091
|
+
evidence_data["role_definitions"] = defender_api.get_and_save_entra_evidence("role_definitions")
|
|
1092
|
+
evidence_data["pim_assignments"] = defender_api.get_and_save_entra_evidence("pim_assignments")
|
|
1093
|
+
evidence_data["pim_eligibility"] = defender_api.get_and_save_entra_evidence("pim_eligibility")
|
|
1094
|
+
|
|
1095
|
+
elif evidence_type == "conditional_access":
|
|
1096
|
+
evidence_data["conditional_access"] = defender_api.get_and_save_entra_evidence("conditional_access")
|
|
1097
|
+
|
|
1098
|
+
elif evidence_type == "authentication":
|
|
1099
|
+
evidence_data["auth_methods_policy"] = defender_api.get_and_save_entra_evidence("auth_methods_policy")
|
|
1100
|
+
evidence_data["user_mfa_registration"] = defender_api.get_and_save_entra_evidence("user_mfa_registration")
|
|
1101
|
+
evidence_data["mfa_registered_users"] = defender_api.get_and_save_entra_evidence("mfa_registered_users")
|
|
1102
|
+
|
|
1103
|
+
elif evidence_type == "audit_logs":
|
|
1104
|
+
evidence_data["sign_in_logs"] = defender_api.get_and_save_entra_evidence("sign_in_logs", start_date=start_date)
|
|
1105
|
+
evidence_data["directory_audits"] = defender_api.get_and_save_entra_evidence(
|
|
1106
|
+
"directory_audits", start_date=start_date
|
|
1107
|
+
)
|
|
1108
|
+
evidence_data["provisioning_logs"] = defender_api.get_and_save_entra_evidence(
|
|
1109
|
+
"provisioning_logs", start_date=start_date
|
|
1110
|
+
)
|
|
1111
|
+
|
|
1112
|
+
elif evidence_type == "access_reviews":
|
|
1113
|
+
evidence_data["access_review_definitions"] = defender_api.collect_entra_access_reviews()
|
|
1114
|
+
|
|
1115
|
+
return evidence_data
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
def get_control_implementations_map(parent_id: int, parent_module: str) -> dict[str, int]:
|
|
1119
|
+
"""
|
|
1120
|
+
Get a mapping of control identifiers to control implementation IDs
|
|
1121
|
+
|
|
1122
|
+
:param int parent_id: RegScale parent ID
|
|
1123
|
+
:param str parent_module: RegScale parent module
|
|
1124
|
+
:return: Dictionary mapping control identifiers (e.g., "AC-2") to control implementation IDs
|
|
1125
|
+
:rtype: dict[str, int]
|
|
1126
|
+
"""
|
|
1127
|
+
from regscale.models import ControlImplementation
|
|
1128
|
+
|
|
1129
|
+
try:
|
|
1130
|
+
control_implementations = ControlImplementation.get_list_by_parent(parent_id, parent_module)
|
|
1131
|
+
if not control_implementations:
|
|
1132
|
+
logger.warning(f"No control implementations found for {parent_module} #{parent_id}")
|
|
1133
|
+
return {}
|
|
1134
|
+
|
|
1135
|
+
control_map = {}
|
|
1136
|
+
for control_impl in control_implementations:
|
|
1137
|
+
# Try to get control identifier from the control object
|
|
1138
|
+
control_id = control_impl.get("controlId") if isinstance(control_impl, dict) else control_impl.controlId
|
|
1139
|
+
id_number = control_impl.get("id") if isinstance(control_impl, dict) else control_impl.id
|
|
1140
|
+
control_map[control_id] = id_number
|
|
1141
|
+
logger.debug(f"Mapped control #{id_number}: {control_id} to implementation.")
|
|
1142
|
+
|
|
1143
|
+
logger.info(f"Found {len(control_map)} control implementations for evidence mapping")
|
|
1144
|
+
return control_map
|
|
1145
|
+
|
|
1146
|
+
except Exception as e:
|
|
1147
|
+
logger.error(f"Error fetching control implementations: {e}")
|
|
1148
|
+
return {}
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
def upload_evidence_to_controls(
|
|
1152
|
+
evidence_key: str,
|
|
1153
|
+
evidence_file_list: list[Path],
|
|
1154
|
+
control_implementations_map: dict[str, int],
|
|
1155
|
+
api: Api,
|
|
1156
|
+
) -> int:
|
|
1157
|
+
"""
|
|
1158
|
+
Upload evidence file to specific control implementations
|
|
1159
|
+
|
|
1160
|
+
:param str evidence_key: Type of evidence (e.g., "users", "sign_in_logs")
|
|
1161
|
+
:param list evidence_file_list: List of evidence files
|
|
1162
|
+
:param dict control_implementations_map: Map of control identifiers to implementation IDs
|
|
1163
|
+
:param Api api: API instance
|
|
1164
|
+
:return: Number of successful uploads
|
|
1165
|
+
:rtype: int
|
|
1166
|
+
"""
|
|
1167
|
+
# Get the controls this evidence type maps to
|
|
1168
|
+
mapped_controls = EVIDENCE_TO_CONTROLS_MAPPING.get(evidence_key, [])
|
|
1169
|
+
if not mapped_controls:
|
|
1170
|
+
logger.warning(f"No control mapping found for evidence type: {evidence_key}")
|
|
1171
|
+
return 0
|
|
1172
|
+
|
|
1173
|
+
# Write evidence data to CSV file
|
|
1174
|
+
successful_uploads = 0
|
|
1175
|
+
for file_path in evidence_file_list:
|
|
1176
|
+
controls_uploaded_to = []
|
|
1177
|
+
file_name = file_path.name
|
|
1178
|
+
|
|
1179
|
+
for control_identifier in mapped_controls:
|
|
1180
|
+
if control_identifier in control_implementations_map:
|
|
1181
|
+
control_impl_id = control_implementations_map[control_identifier]
|
|
1182
|
+
|
|
1183
|
+
# Upload file to specific control implementation
|
|
1184
|
+
if File.upload_file_to_regscale(
|
|
1185
|
+
file_name=file_path.absolute(), # type: ignore
|
|
1186
|
+
parent_id=control_impl_id,
|
|
1187
|
+
parent_module="controls",
|
|
1188
|
+
api=api,
|
|
1189
|
+
):
|
|
1190
|
+
successful_uploads += 1
|
|
1191
|
+
controls_uploaded_to.append(control_identifier)
|
|
1192
|
+
logger.debug(
|
|
1193
|
+
f"Successfully uploaded {file_name} to control {control_identifier} (ID: {control_impl_id})"
|
|
1194
|
+
)
|
|
1195
|
+
else:
|
|
1196
|
+
logger.error(
|
|
1197
|
+
f"Failed to upload {file_name} to control {control_identifier} (ID: {control_impl_id})"
|
|
1198
|
+
)
|
|
1199
|
+
|
|
1200
|
+
if controls_uploaded_to:
|
|
1201
|
+
logger.info(
|
|
1202
|
+
f"Successfully uploaded {file_name} to {len(controls_uploaded_to)} controls: {', '.join(controls_uploaded_to)}"
|
|
1203
|
+
)
|
|
1204
|
+
else:
|
|
1205
|
+
logger.warning(f"No matching control implementations found for {evidence_key} evidence")
|
|
1206
|
+
|
|
1207
|
+
return successful_uploads
|
|
1208
|
+
|
|
1209
|
+
|
|
1210
|
+
def upload_evidence_files(
|
|
1211
|
+
evidence_data: dict[str, list[Path]], parent_id: int, parent_module: str, api: Api, evidence_type: str
|
|
1212
|
+
) -> None:
|
|
1213
|
+
"""
|
|
1214
|
+
Upload evidence files to specific RegScale control implementations
|
|
1215
|
+
|
|
1216
|
+
:param dict[str, list[Path]] evidence_data: Dictionary containing evidence data
|
|
1217
|
+
:param int parent_id: RegScale parent ID
|
|
1218
|
+
:param str parent_module: RegScale parent module
|
|
1219
|
+
:param Api api: API instance
|
|
1220
|
+
:param str evidence_type: Type of evidence collected
|
|
1221
|
+
:rtype: None
|
|
1222
|
+
"""
|
|
1223
|
+
from regscale.integrations.commercial.microsoft_defender.defender_constants import EVIDENCE_CATEGORIES
|
|
1224
|
+
|
|
1225
|
+
artifacts_dir = Path("./artifacts")
|
|
1226
|
+
artifacts_dir.mkdir(exist_ok=True)
|
|
1227
|
+
|
|
1228
|
+
# Get control implementations mapping for evidence targeting
|
|
1229
|
+
control_implementations_map = get_control_implementations_map(parent_id, parent_module)
|
|
1230
|
+
|
|
1231
|
+
if not control_implementations_map:
|
|
1232
|
+
logger.error(
|
|
1233
|
+
f"No control implementations found for {parent_module} #{parent_id}. Cannot map evidence to controls."
|
|
1234
|
+
)
|
|
1235
|
+
return
|
|
1236
|
+
|
|
1237
|
+
total_successful_uploads = 0
|
|
1238
|
+
total_evidence_items = 0
|
|
1239
|
+
evidence_summary = []
|
|
1240
|
+
|
|
1241
|
+
for evidence_key, evidence_list in evidence_data.items():
|
|
1242
|
+
if not evidence_list:
|
|
1243
|
+
logger.warning(f"No data found for {evidence_key}")
|
|
1244
|
+
continue
|
|
1245
|
+
|
|
1246
|
+
total_evidence_items += len(evidence_list)
|
|
1247
|
+
|
|
1248
|
+
# Upload evidence to specific control implementations
|
|
1249
|
+
uploads_for_evidence = upload_evidence_to_controls(
|
|
1250
|
+
evidence_key=evidence_key,
|
|
1251
|
+
evidence_file_list=evidence_list,
|
|
1252
|
+
control_implementations_map=control_implementations_map,
|
|
1253
|
+
api=api,
|
|
1254
|
+
)
|
|
1255
|
+
|
|
1256
|
+
total_successful_uploads += uploads_for_evidence
|
|
1257
|
+
evidence_summary.append(f"{evidence_key}: {len(evidence_list)} items → {uploads_for_evidence} control uploads")
|
|
1258
|
+
|
|
1259
|
+
# Summary
|
|
1260
|
+
category_name = EVIDENCE_CATEGORIES.get(evidence_type, f"Azure Entra {evidence_type.replace('_', ' ').title()}")
|
|
1261
|
+
logger.info(
|
|
1262
|
+
f"Azure Entra evidence collection complete for {category_name}. "
|
|
1263
|
+
f"Collected {total_evidence_items} total items across {total_successful_uploads} control-specific uploads."
|
|
1264
|
+
)
|
|
1265
|
+
|
|
1266
|
+
# Detailed summary
|
|
1267
|
+
if evidence_summary:
|
|
1268
|
+
logger.info("Evidence upload summary:")
|
|
1269
|
+
for summary in evidence_summary:
|
|
1270
|
+
logger.info(f" - {summary}")
|