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
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""AWS IAM Control Mappings for RegScale Compliance Integration."""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Dict, List, Optional
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger("regscale")
|
|
9
|
+
|
|
10
|
+
# NIST 800-53 R5 Control Mappings for AWS IAM
|
|
11
|
+
IAM_CONTROL_MAPPINGS = {
|
|
12
|
+
"AC-2": {
|
|
13
|
+
"name": "Account Management",
|
|
14
|
+
"description": "Manage system accounts including creation, enabling, modification, and removal",
|
|
15
|
+
"checks": {
|
|
16
|
+
"user_mfa": {
|
|
17
|
+
"weight": 100,
|
|
18
|
+
"pass_criteria": "All IAM users have MFA enabled",
|
|
19
|
+
"fail_criteria": "IAM users without MFA enabled",
|
|
20
|
+
},
|
|
21
|
+
"inactive_users": {
|
|
22
|
+
"weight": 90,
|
|
23
|
+
"pass_criteria": "No inactive users (password age > 90 days)",
|
|
24
|
+
"fail_criteria": "Users with credentials unused for extended period",
|
|
25
|
+
},
|
|
26
|
+
"root_account_usage": {
|
|
27
|
+
"weight": 100,
|
|
28
|
+
"pass_criteria": "Root account has MFA and no access keys",
|
|
29
|
+
"fail_criteria": "Root account without MFA or with active access keys",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
"AC-6": {
|
|
34
|
+
"name": "Least Privilege",
|
|
35
|
+
"description": "Employ the principle of least privilege",
|
|
36
|
+
"checks": {
|
|
37
|
+
"admin_policies": {
|
|
38
|
+
"weight": 100,
|
|
39
|
+
"pass_criteria": "No users with direct AdministratorAccess policy attachment",
|
|
40
|
+
"fail_criteria": "Users with full admin (*:*) permissions",
|
|
41
|
+
},
|
|
42
|
+
"inline_policies": {
|
|
43
|
+
"weight": 80,
|
|
44
|
+
"pass_criteria": "Minimal use of inline policies, prefer managed policies",
|
|
45
|
+
"fail_criteria": "Excessive inline policies indicating poor policy management",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
"IA-2": {
|
|
50
|
+
"name": "Identification and Authentication (Organizational Users)",
|
|
51
|
+
"description": "Uniquely identify and authenticate organizational users",
|
|
52
|
+
"checks": {
|
|
53
|
+
"password_policy": {
|
|
54
|
+
"weight": 100,
|
|
55
|
+
"pass_criteria": "Strong password policy enforced (length, complexity, rotation)",
|
|
56
|
+
"fail_criteria": "Weak or no password policy",
|
|
57
|
+
},
|
|
58
|
+
"mfa_enforcement": {
|
|
59
|
+
"weight": 100,
|
|
60
|
+
"pass_criteria": "MFA required for all users",
|
|
61
|
+
"fail_criteria": "Users without MFA",
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
"IA-5": {
|
|
66
|
+
"name": "Authenticator Management",
|
|
67
|
+
"description": "Manage system authenticators",
|
|
68
|
+
"checks": {
|
|
69
|
+
"access_key_rotation": {
|
|
70
|
+
"weight": 100,
|
|
71
|
+
"pass_criteria": "Access keys rotated within 90 days",
|
|
72
|
+
"fail_criteria": "Access keys older than 90 days",
|
|
73
|
+
},
|
|
74
|
+
"unused_credentials": {
|
|
75
|
+
"weight": 90,
|
|
76
|
+
"pass_criteria": "No unused credentials (password or access keys)",
|
|
77
|
+
"fail_criteria": "Credentials not used in 90+ days",
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
"AC-3": {
|
|
82
|
+
"name": "Access Enforcement",
|
|
83
|
+
"description": "Enforce approved authorizations for logical access",
|
|
84
|
+
"checks": {
|
|
85
|
+
"role_trust_policies": {
|
|
86
|
+
"weight": 100,
|
|
87
|
+
"pass_criteria": "IAM roles have restrictive trust policies",
|
|
88
|
+
"fail_criteria": "Roles with overly permissive trust relationships",
|
|
89
|
+
},
|
|
90
|
+
"group_based_access": {
|
|
91
|
+
"weight": 80,
|
|
92
|
+
"pass_criteria": "Users assigned to groups rather than direct policy attachments",
|
|
93
|
+
"fail_criteria": "Users with direct policy attachments instead of group membership",
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
# ISO 27001 Control Mappings
|
|
100
|
+
ISO_27001_MAPPINGS = {
|
|
101
|
+
"A.9.2.1": {
|
|
102
|
+
"name": "User registration and de-registration",
|
|
103
|
+
"iam_attributes": ["users", "user_status", "last_activity"],
|
|
104
|
+
},
|
|
105
|
+
"A.9.2.2": {
|
|
106
|
+
"name": "User access provisioning",
|
|
107
|
+
"iam_attributes": ["policies", "groups", "roles"],
|
|
108
|
+
},
|
|
109
|
+
"A.9.4.3": {
|
|
110
|
+
"name": "Password management system",
|
|
111
|
+
"iam_attributes": ["password_policy", "mfa_status"],
|
|
112
|
+
},
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
# Password policy requirements (strong policy)
|
|
116
|
+
STRONG_PASSWORD_POLICY = {
|
|
117
|
+
"MinimumPasswordLength": 14,
|
|
118
|
+
"RequireSymbols": True,
|
|
119
|
+
"RequireNumbers": True,
|
|
120
|
+
"RequireUppercaseCharacters": True,
|
|
121
|
+
"RequireLowercaseCharacters": True,
|
|
122
|
+
"MaxPasswordAge": 90,
|
|
123
|
+
"PasswordReusePrevention": 24,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# Age thresholds (in days)
|
|
127
|
+
ACCESS_KEY_MAX_AGE_DAYS = 90
|
|
128
|
+
PASSWORD_MAX_AGE_DAYS = 90
|
|
129
|
+
CREDENTIAL_UNUSED_DAYS = 90
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class IAMControlMapper:
|
|
133
|
+
"""Map AWS IAM resources to compliance control status."""
|
|
134
|
+
|
|
135
|
+
def __init__(self, framework: str = "NIST800-53R5"):
|
|
136
|
+
"""
|
|
137
|
+
Initialize IAM control mapper.
|
|
138
|
+
|
|
139
|
+
:param str framework: Compliance framework (NIST800-53R5 or ISO27001)
|
|
140
|
+
"""
|
|
141
|
+
self.framework = framework
|
|
142
|
+
self.mappings = IAM_CONTROL_MAPPINGS if framework == "NIST800-53R5" else ISO_27001_MAPPINGS
|
|
143
|
+
|
|
144
|
+
def assess_iam_compliance(self, iam_data: Dict) -> Dict[str, str]:
|
|
145
|
+
"""
|
|
146
|
+
Assess AWS IAM compliance against all mapped controls.
|
|
147
|
+
|
|
148
|
+
:param Dict iam_data: IAM resources and configuration
|
|
149
|
+
:return: Dictionary mapping control IDs to compliance results (PASS/FAIL)
|
|
150
|
+
:rtype: Dict[str, str]
|
|
151
|
+
"""
|
|
152
|
+
results = {}
|
|
153
|
+
|
|
154
|
+
if self.framework == "NIST800-53R5":
|
|
155
|
+
results["AC-2"] = self._assess_ac2(iam_data)
|
|
156
|
+
results["AC-6"] = self._assess_ac6(iam_data)
|
|
157
|
+
results["IA-2"] = self._assess_ia2(iam_data)
|
|
158
|
+
results["IA-5"] = self._assess_ia5(iam_data)
|
|
159
|
+
results["AC-3"] = self._assess_ac3(iam_data)
|
|
160
|
+
|
|
161
|
+
return results
|
|
162
|
+
|
|
163
|
+
def _assess_ac2(self, iam_data: Dict) -> str:
|
|
164
|
+
"""
|
|
165
|
+
Assess AC-2 (Account Management) compliance.
|
|
166
|
+
|
|
167
|
+
:param Dict iam_data: IAM data
|
|
168
|
+
:return: Compliance result (PASS/FAIL)
|
|
169
|
+
:rtype: str
|
|
170
|
+
"""
|
|
171
|
+
users = iam_data.get("users", [])
|
|
172
|
+
account_summary = iam_data.get("account_summary", {})
|
|
173
|
+
|
|
174
|
+
# Check MFA for users
|
|
175
|
+
users_without_mfa = [u for u in users if not u.get("MfaEnabled", False)]
|
|
176
|
+
if users_without_mfa:
|
|
177
|
+
logger.debug(f"IAM FAILS AC-2: {len(users_without_mfa)} users without MFA")
|
|
178
|
+
return "FAIL"
|
|
179
|
+
|
|
180
|
+
# Check root account
|
|
181
|
+
root_mfa = account_summary.get("AccountMFAEnabled", False)
|
|
182
|
+
if not root_mfa:
|
|
183
|
+
logger.debug("IAM FAILS AC-2: Root account does not have MFA enabled")
|
|
184
|
+
return "FAIL"
|
|
185
|
+
|
|
186
|
+
# Check for root access keys
|
|
187
|
+
root_access_keys = account_summary.get("AccountAccessKeysPresent", 0)
|
|
188
|
+
if root_access_keys > 0:
|
|
189
|
+
logger.debug("IAM FAILS AC-2: Root account has active access keys")
|
|
190
|
+
return "FAIL"
|
|
191
|
+
|
|
192
|
+
logger.debug("IAM PASSES AC-2: All users have MFA, root account secured")
|
|
193
|
+
return "PASS"
|
|
194
|
+
|
|
195
|
+
def _assess_ac6(self, iam_data: Dict) -> str:
|
|
196
|
+
"""
|
|
197
|
+
Assess AC-6 (Least Privilege) compliance.
|
|
198
|
+
|
|
199
|
+
:param Dict iam_data: IAM data
|
|
200
|
+
:return: Compliance result (PASS/FAIL)
|
|
201
|
+
:rtype: str
|
|
202
|
+
"""
|
|
203
|
+
users = iam_data.get("users", [])
|
|
204
|
+
|
|
205
|
+
# Check for users with AdministratorAccess
|
|
206
|
+
users_with_admin = []
|
|
207
|
+
for user in users:
|
|
208
|
+
attached_policies = user.get("AttachedPolicies", [])
|
|
209
|
+
inline_policies = user.get("InlinePolicies", [])
|
|
210
|
+
|
|
211
|
+
# Check attached policies
|
|
212
|
+
if any("AdministratorAccess" in p.get("PolicyName", "") for p in attached_policies):
|
|
213
|
+
users_with_admin.append(user.get("UserName"))
|
|
214
|
+
|
|
215
|
+
# Check inline policies for broad permissions
|
|
216
|
+
for policy in inline_policies:
|
|
217
|
+
policy_doc = policy.get("PolicyDocument", {})
|
|
218
|
+
if self._has_full_admin_permissions(policy_doc):
|
|
219
|
+
users_with_admin.append(user.get("UserName"))
|
|
220
|
+
|
|
221
|
+
if users_with_admin:
|
|
222
|
+
logger.debug(f"IAM FAILS AC-6: {len(users_with_admin)} users with administrator access")
|
|
223
|
+
return "FAIL"
|
|
224
|
+
|
|
225
|
+
logger.debug("IAM PASSES AC-6: No users with direct administrator access")
|
|
226
|
+
return "PASS"
|
|
227
|
+
|
|
228
|
+
def _assess_ia2(self, iam_data: Dict) -> str:
|
|
229
|
+
"""
|
|
230
|
+
Assess IA-2 (Identification and Authentication) compliance.
|
|
231
|
+
|
|
232
|
+
:param Dict iam_data: IAM data
|
|
233
|
+
:return: Compliance result (PASS/FAIL)
|
|
234
|
+
:rtype: str
|
|
235
|
+
"""
|
|
236
|
+
users = iam_data.get("users", [])
|
|
237
|
+
password_policy = iam_data.get("password_policy", {})
|
|
238
|
+
|
|
239
|
+
# Check password policy strength
|
|
240
|
+
if not self._is_strong_password_policy(password_policy):
|
|
241
|
+
logger.debug("IAM FAILS IA-2: Weak password policy")
|
|
242
|
+
return "FAIL"
|
|
243
|
+
|
|
244
|
+
# Check MFA enforcement
|
|
245
|
+
users_without_mfa = [u for u in users if not u.get("MfaEnabled", False)]
|
|
246
|
+
if users_without_mfa:
|
|
247
|
+
logger.debug(f"IAM FAILS IA-2: {len(users_without_mfa)} users without MFA")
|
|
248
|
+
return "FAIL"
|
|
249
|
+
|
|
250
|
+
logger.debug("IAM PASSES IA-2: Strong password policy and MFA enforced")
|
|
251
|
+
return "PASS"
|
|
252
|
+
|
|
253
|
+
def _assess_ia5(self, iam_data: Dict) -> str:
|
|
254
|
+
"""
|
|
255
|
+
Assess IA-5 (Authenticator Management) compliance.
|
|
256
|
+
|
|
257
|
+
:param Dict iam_data: IAM data
|
|
258
|
+
:return: Compliance result (PASS/FAIL)
|
|
259
|
+
:rtype: str
|
|
260
|
+
"""
|
|
261
|
+
users = iam_data.get("users", [])
|
|
262
|
+
|
|
263
|
+
# Check access key age
|
|
264
|
+
old_access_keys = []
|
|
265
|
+
unused_credentials = []
|
|
266
|
+
|
|
267
|
+
for user in users:
|
|
268
|
+
access_keys = user.get("AccessKeys", [])
|
|
269
|
+
for key in access_keys:
|
|
270
|
+
age_days = key.get("AgeDays", 0)
|
|
271
|
+
if age_days > ACCESS_KEY_MAX_AGE_DAYS:
|
|
272
|
+
old_access_keys.append(key.get("AccessKeyId"))
|
|
273
|
+
|
|
274
|
+
# Check credential usage
|
|
275
|
+
password_last_used = user.get("PasswordLastUsed")
|
|
276
|
+
if password_last_used and password_last_used.get("DaysSinceUsed", 0) > CREDENTIAL_UNUSED_DAYS:
|
|
277
|
+
unused_credentials.append(user.get("UserName"))
|
|
278
|
+
|
|
279
|
+
if old_access_keys:
|
|
280
|
+
logger.debug(
|
|
281
|
+
f"IAM FAILS IA-5: {len(old_access_keys)} access keys older than {ACCESS_KEY_MAX_AGE_DAYS} days"
|
|
282
|
+
)
|
|
283
|
+
return "FAIL"
|
|
284
|
+
|
|
285
|
+
if unused_credentials:
|
|
286
|
+
logger.debug(f"IAM FAILS IA-5: {len(unused_credentials)} users with unused credentials")
|
|
287
|
+
return "FAIL"
|
|
288
|
+
|
|
289
|
+
logger.debug("IAM PASSES IA-5: All access keys rotated, no unused credentials")
|
|
290
|
+
return "PASS"
|
|
291
|
+
|
|
292
|
+
def _assess_ac3(self, iam_data: Dict) -> str:
|
|
293
|
+
"""
|
|
294
|
+
Assess AC-3 (Access Enforcement) compliance.
|
|
295
|
+
|
|
296
|
+
:param Dict iam_data: IAM data
|
|
297
|
+
:return: Compliance result (PASS/FAIL)
|
|
298
|
+
:rtype: str
|
|
299
|
+
"""
|
|
300
|
+
roles = iam_data.get("roles", [])
|
|
301
|
+
|
|
302
|
+
# Check for overly permissive role trust policies
|
|
303
|
+
permissive_roles = []
|
|
304
|
+
for role in roles:
|
|
305
|
+
trust_policy = role.get("AssumeRolePolicyDocument", {})
|
|
306
|
+
if self._has_permissive_trust_policy(trust_policy):
|
|
307
|
+
permissive_roles.append(role.get("RoleName"))
|
|
308
|
+
|
|
309
|
+
if permissive_roles:
|
|
310
|
+
logger.debug(f"IAM FAILS AC-3: {len(permissive_roles)} roles with overly permissive trust policies")
|
|
311
|
+
return "FAIL"
|
|
312
|
+
|
|
313
|
+
logger.debug("IAM PASSES AC-3: All roles have restrictive trust policies")
|
|
314
|
+
return "PASS"
|
|
315
|
+
|
|
316
|
+
def _has_full_admin_permissions(self, policy_doc: Dict) -> bool:
|
|
317
|
+
"""Check if policy grants full admin permissions."""
|
|
318
|
+
statements = policy_doc.get("Statement", [])
|
|
319
|
+
for statement in statements:
|
|
320
|
+
if statement.get("Effect") == "Allow":
|
|
321
|
+
actions = statement.get("Action", [])
|
|
322
|
+
resources = statement.get("Resource", [])
|
|
323
|
+
if ("*" in actions or "*:*" in actions) and ("*" in resources):
|
|
324
|
+
return True
|
|
325
|
+
return False
|
|
326
|
+
|
|
327
|
+
def _has_permissive_trust_policy(self, trust_policy: Dict) -> bool:
|
|
328
|
+
"""Check if trust policy is overly permissive."""
|
|
329
|
+
statements = trust_policy.get("Statement", [])
|
|
330
|
+
for statement in statements:
|
|
331
|
+
principal = statement.get("Principal", {})
|
|
332
|
+
if principal == "*" or (isinstance(principal, dict) and principal.get("AWS") == "*"):
|
|
333
|
+
return True
|
|
334
|
+
return False
|
|
335
|
+
|
|
336
|
+
def _is_strong_password_policy(self, policy: Dict) -> bool:
|
|
337
|
+
"""Check if password policy meets strong requirements."""
|
|
338
|
+
if not policy:
|
|
339
|
+
return False
|
|
340
|
+
|
|
341
|
+
checks = [
|
|
342
|
+
policy.get("MinimumPasswordLength", 0) >= STRONG_PASSWORD_POLICY["MinimumPasswordLength"],
|
|
343
|
+
policy.get("RequireSymbols", False),
|
|
344
|
+
policy.get("RequireNumbers", False),
|
|
345
|
+
policy.get("RequireUppercaseCharacters", False),
|
|
346
|
+
policy.get("RequireLowercaseCharacters", False),
|
|
347
|
+
policy.get("MaxPasswordAge", 0) <= STRONG_PASSWORD_POLICY["MaxPasswordAge"],
|
|
348
|
+
]
|
|
349
|
+
|
|
350
|
+
return all(checks)
|
|
351
|
+
|
|
352
|
+
def get_control_description(self, control_id: str) -> Optional[str]:
|
|
353
|
+
"""Get human-readable description for a control."""
|
|
354
|
+
control_data = self.mappings.get(control_id)
|
|
355
|
+
if control_data:
|
|
356
|
+
return f"{control_data.get('name')}: {control_data.get('description', '')}"
|
|
357
|
+
return None
|
|
358
|
+
|
|
359
|
+
def get_mapped_controls(self) -> List[str]:
|
|
360
|
+
"""Get list of all control IDs mapped for this framework."""
|
|
361
|
+
return list(self.mappings.keys())
|
|
362
|
+
|
|
363
|
+
def get_check_details(self, control_id: str) -> Optional[Dict]:
|
|
364
|
+
"""Get detailed check criteria for a control."""
|
|
365
|
+
control_data = self.mappings.get(control_id)
|
|
366
|
+
if control_data:
|
|
367
|
+
return control_data.get("checks", {})
|
|
368
|
+
return None
|