regscale-cli 6.27.2.0__py3-none-any.whl → 6.28.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.

Files changed (140) hide show
  1. regscale/_version.py +1 -1
  2. regscale/core/app/application.py +1 -0
  3. regscale/core/app/internal/control_editor.py +73 -21
  4. regscale/core/app/internal/login.py +4 -1
  5. regscale/core/app/internal/model_editor.py +219 -64
  6. regscale/core/app/utils/app_utils.py +11 -2
  7. regscale/core/login.py +21 -4
  8. regscale/core/utils/date.py +77 -1
  9. regscale/dev/cli.py +26 -0
  10. regscale/dev/version.py +72 -0
  11. regscale/integrations/commercial/__init__.py +15 -1
  12. regscale/integrations/commercial/amazon/amazon/__init__.py +0 -0
  13. regscale/integrations/commercial/amazon/amazon/common.py +204 -0
  14. regscale/integrations/commercial/amazon/common.py +48 -58
  15. regscale/integrations/commercial/aws/audit_manager_compliance.py +2671 -0
  16. regscale/integrations/commercial/aws/cli.py +3093 -55
  17. regscale/integrations/commercial/aws/cloudtrail_control_mappings.py +333 -0
  18. regscale/integrations/commercial/aws/cloudtrail_evidence.py +501 -0
  19. regscale/integrations/commercial/aws/cloudwatch_control_mappings.py +357 -0
  20. regscale/integrations/commercial/aws/cloudwatch_evidence.py +490 -0
  21. regscale/integrations/commercial/aws/config_compliance.py +914 -0
  22. regscale/integrations/commercial/aws/conformance_pack_mappings.py +198 -0
  23. regscale/integrations/commercial/aws/evidence_generator.py +283 -0
  24. regscale/integrations/commercial/aws/guardduty_control_mappings.py +340 -0
  25. regscale/integrations/commercial/aws/guardduty_evidence.py +1053 -0
  26. regscale/integrations/commercial/aws/iam_control_mappings.py +368 -0
  27. regscale/integrations/commercial/aws/iam_evidence.py +574 -0
  28. regscale/integrations/commercial/aws/inventory/__init__.py +223 -22
  29. regscale/integrations/commercial/aws/inventory/base.py +107 -5
  30. regscale/integrations/commercial/aws/inventory/resources/audit_manager.py +513 -0
  31. regscale/integrations/commercial/aws/inventory/resources/cloudtrail.py +315 -0
  32. regscale/integrations/commercial/aws/inventory/resources/cloudtrail_logs_metadata.py +476 -0
  33. regscale/integrations/commercial/aws/inventory/resources/cloudwatch.py +191 -0
  34. regscale/integrations/commercial/aws/inventory/resources/compute.py +66 -9
  35. regscale/integrations/commercial/aws/inventory/resources/config.py +464 -0
  36. regscale/integrations/commercial/aws/inventory/resources/containers.py +74 -9
  37. regscale/integrations/commercial/aws/inventory/resources/database.py +106 -31
  38. regscale/integrations/commercial/aws/inventory/resources/guardduty.py +286 -0
  39. regscale/integrations/commercial/aws/inventory/resources/iam.py +470 -0
  40. regscale/integrations/commercial/aws/inventory/resources/inspector.py +476 -0
  41. regscale/integrations/commercial/aws/inventory/resources/integration.py +175 -61
  42. regscale/integrations/commercial/aws/inventory/resources/kms.py +447 -0
  43. regscale/integrations/commercial/aws/inventory/resources/networking.py +103 -67
  44. regscale/integrations/commercial/aws/inventory/resources/s3.py +394 -0
  45. regscale/integrations/commercial/aws/inventory/resources/security.py +268 -72
  46. regscale/integrations/commercial/aws/inventory/resources/securityhub.py +473 -0
  47. regscale/integrations/commercial/aws/inventory/resources/storage.py +53 -29
  48. regscale/integrations/commercial/aws/inventory/resources/systems_manager.py +657 -0
  49. regscale/integrations/commercial/aws/inventory/resources/vpc.py +655 -0
  50. regscale/integrations/commercial/aws/kms_control_mappings.py +288 -0
  51. regscale/integrations/commercial/aws/kms_evidence.py +879 -0
  52. regscale/integrations/commercial/aws/ocsf/__init__.py +7 -0
  53. regscale/integrations/commercial/aws/ocsf/constants.py +115 -0
  54. regscale/integrations/commercial/aws/ocsf/mapper.py +435 -0
  55. regscale/integrations/commercial/aws/org_control_mappings.py +286 -0
  56. regscale/integrations/commercial/aws/org_evidence.py +666 -0
  57. regscale/integrations/commercial/aws/s3_control_mappings.py +356 -0
  58. regscale/integrations/commercial/aws/s3_evidence.py +632 -0
  59. regscale/integrations/commercial/aws/scanner.py +853 -205
  60. regscale/integrations/commercial/aws/security_hub.py +319 -0
  61. regscale/integrations/commercial/aws/session_manager.py +282 -0
  62. regscale/integrations/commercial/aws/ssm_control_mappings.py +291 -0
  63. regscale/integrations/commercial/aws/ssm_evidence.py +492 -0
  64. regscale/integrations/commercial/synqly/query_builder.py +4 -1
  65. regscale/integrations/compliance_integration.py +308 -38
  66. regscale/integrations/control_matcher.py +78 -23
  67. regscale/integrations/due_date_handler.py +3 -0
  68. regscale/integrations/public/csam/csam.py +572 -763
  69. regscale/integrations/public/csam/csam_agency_defined.py +179 -0
  70. regscale/integrations/public/csam/csam_common.py +154 -0
  71. regscale/integrations/public/csam/csam_controls.py +432 -0
  72. regscale/integrations/public/csam/csam_poam.py +124 -0
  73. regscale/integrations/public/fedramp/click.py +17 -4
  74. regscale/integrations/public/fedramp/fedramp_cis_crm.py +271 -62
  75. regscale/integrations/public/fedramp/poam/scanner.py +74 -7
  76. regscale/integrations/scanner_integration.py +415 -85
  77. regscale/models/integration_models/cisa_kev_data.json +80 -20
  78. regscale/models/integration_models/synqly_models/capabilities.json +1 -1
  79. regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +44 -3
  80. regscale/models/integration_models/synqly_models/ocsf_mapper.py +41 -12
  81. regscale/models/platform.py +3 -0
  82. regscale/models/regscale_models/__init__.py +5 -0
  83. regscale/models/regscale_models/assessment.py +2 -1
  84. regscale/models/regscale_models/component.py +1 -1
  85. regscale/models/regscale_models/control_implementation.py +55 -24
  86. regscale/models/regscale_models/control_objective.py +74 -5
  87. regscale/models/regscale_models/file.py +2 -0
  88. regscale/models/regscale_models/issue.py +2 -5
  89. regscale/models/regscale_models/organization.py +3 -0
  90. regscale/models/regscale_models/regscale_model.py +17 -5
  91. regscale/models/regscale_models/security_plan.py +1 -0
  92. regscale/regscale.py +11 -1
  93. {regscale_cli-6.27.2.0.dist-info → regscale_cli-6.28.0.0.dist-info}/METADATA +1 -1
  94. {regscale_cli-6.27.2.0.dist-info → regscale_cli-6.28.0.0.dist-info}/RECORD +140 -57
  95. tests/regscale/core/test_login.py +171 -4
  96. tests/regscale/integrations/commercial/aws/__init__.py +0 -0
  97. tests/regscale/integrations/commercial/aws/test_audit_manager_compliance.py +1304 -0
  98. tests/regscale/integrations/commercial/aws/test_audit_manager_evidence_aggregation.py +341 -0
  99. tests/regscale/integrations/commercial/aws/test_aws_audit_manager_collector.py +1155 -0
  100. tests/regscale/integrations/commercial/aws/test_aws_cloudtrail_collector.py +534 -0
  101. tests/regscale/integrations/commercial/aws/test_aws_config_collector.py +400 -0
  102. tests/regscale/integrations/commercial/aws/test_aws_guardduty_collector.py +315 -0
  103. tests/regscale/integrations/commercial/aws/test_aws_iam_collector.py +458 -0
  104. tests/regscale/integrations/commercial/aws/test_aws_inspector_collector.py +353 -0
  105. tests/regscale/integrations/commercial/aws/test_aws_inventory_integration.py +530 -0
  106. tests/regscale/integrations/commercial/aws/test_aws_kms_collector.py +919 -0
  107. tests/regscale/integrations/commercial/aws/test_aws_s3_collector.py +722 -0
  108. tests/regscale/integrations/commercial/aws/test_aws_scanner_integration.py +722 -0
  109. tests/regscale/integrations/commercial/aws/test_aws_securityhub_collector.py +792 -0
  110. tests/regscale/integrations/commercial/aws/test_aws_systems_manager_collector.py +918 -0
  111. tests/regscale/integrations/commercial/aws/test_aws_vpc_collector.py +996 -0
  112. tests/regscale/integrations/commercial/aws/test_cli_evidence.py +431 -0
  113. tests/regscale/integrations/commercial/aws/test_cloudtrail_control_mappings.py +452 -0
  114. tests/regscale/integrations/commercial/aws/test_cloudtrail_evidence.py +788 -0
  115. tests/regscale/integrations/commercial/aws/test_config_compliance.py +298 -0
  116. tests/regscale/integrations/commercial/aws/test_conformance_pack_mappings.py +200 -0
  117. tests/regscale/integrations/commercial/aws/test_evidence_generator.py +386 -0
  118. tests/regscale/integrations/commercial/aws/test_guardduty_control_mappings.py +564 -0
  119. tests/regscale/integrations/commercial/aws/test_guardduty_evidence.py +1041 -0
  120. tests/regscale/integrations/commercial/aws/test_iam_control_mappings.py +718 -0
  121. tests/regscale/integrations/commercial/aws/test_iam_evidence.py +1375 -0
  122. tests/regscale/integrations/commercial/aws/test_kms_control_mappings.py +656 -0
  123. tests/regscale/integrations/commercial/aws/test_kms_evidence.py +1163 -0
  124. tests/regscale/integrations/commercial/aws/test_ocsf_mapper.py +370 -0
  125. tests/regscale/integrations/commercial/aws/test_org_control_mappings.py +546 -0
  126. tests/regscale/integrations/commercial/aws/test_org_evidence.py +1240 -0
  127. tests/regscale/integrations/commercial/aws/test_s3_control_mappings.py +672 -0
  128. tests/regscale/integrations/commercial/aws/test_s3_evidence.py +987 -0
  129. tests/regscale/integrations/commercial/aws/test_scanner_evidence.py +373 -0
  130. tests/regscale/integrations/commercial/aws/test_security_hub_config_filtering.py +539 -0
  131. tests/regscale/integrations/commercial/aws/test_session_manager.py +516 -0
  132. tests/regscale/integrations/commercial/aws/test_ssm_control_mappings.py +588 -0
  133. tests/regscale/integrations/commercial/aws/test_ssm_evidence.py +735 -0
  134. tests/regscale/integrations/commercial/test_aws.py +55 -56
  135. tests/regscale/integrations/test_control_matcher.py +24 -0
  136. tests/regscale/models/test_control_implementation.py +118 -3
  137. {regscale_cli-6.27.2.0.dist-info → regscale_cli-6.28.0.0.dist-info}/LICENSE +0 -0
  138. {regscale_cli-6.27.2.0.dist-info → regscale_cli-6.28.0.0.dist-info}/WHEEL +0 -0
  139. {regscale_cli-6.27.2.0.dist-info → regscale_cli-6.28.0.0.dist-info}/entry_points.txt +0 -0
  140. {regscale_cli-6.27.2.0.dist-info → regscale_cli-6.28.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,286 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """AWS Organizations 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 Organizations
11
+ ORG_CONTROL_MAPPINGS = {
12
+ "AC-1": {
13
+ "name": "Policy and Procedures",
14
+ "description": "Develop, document, and disseminate access control policy and procedures",
15
+ "checks": {
16
+ "scp_attached": {
17
+ "weight": 100,
18
+ "pass_criteria": "Organization has Service Control Policies attached to enforce access controls",
19
+ "fail_criteria": "No SCPs attached or SCPs not enforcing proper access restrictions",
20
+ },
21
+ "organizational_structure": {
22
+ "weight": 80,
23
+ "pass_criteria": "Clear OU hierarchy established for governance",
24
+ "fail_criteria": "Flat structure with no organizational units",
25
+ },
26
+ },
27
+ },
28
+ "PM-9": {
29
+ "name": "Risk Management Strategy",
30
+ "description": "Develop comprehensive risk management strategy for the organization",
31
+ "checks": {
32
+ "account_governance": {
33
+ "weight": 100,
34
+ "pass_criteria": "Accounts organized by risk profile (prod, dev, sandbox) with appropriate SCPs",
35
+ "fail_criteria": "All accounts in same OU without risk-based segmentation",
36
+ },
37
+ "policy_enforcement": {
38
+ "weight": 90,
39
+ "pass_criteria": "SCPs enforce security guardrails (e.g., region restrictions, service restrictions)",
40
+ "fail_criteria": "No restrictive SCPs or only default FullAWSAccess policy",
41
+ },
42
+ },
43
+ },
44
+ "AC-2": {
45
+ "name": "Account Management",
46
+ "description": "Manage system accounts including creation, enabling, modification, and removal",
47
+ "checks": {
48
+ "active_accounts": {
49
+ "weight": 100,
50
+ "pass_criteria": "All accounts are ACTIVE with proper metadata (email, name)",
51
+ "fail_criteria": "SUSPENDED or accounts missing contact information",
52
+ },
53
+ "account_tracking": {
54
+ "weight": 80,
55
+ "pass_criteria": "Accounts have tags or metadata for ownership and purpose",
56
+ "fail_criteria": "Accounts lack identification or ownership information",
57
+ },
58
+ },
59
+ },
60
+ "AC-6": {
61
+ "name": "Least Privilege",
62
+ "description": "Employ the principle of least privilege",
63
+ "checks": {
64
+ "restrictive_scps": {
65
+ "weight": 100,
66
+ "pass_criteria": "SCPs implement least privilege by denying unnecessary services/actions",
67
+ "fail_criteria": "SCPs use FullAWSAccess or overly permissive policies",
68
+ },
69
+ },
70
+ },
71
+ }
72
+
73
+ # ISO 27001 Control Mappings
74
+ ISO_27001_MAPPINGS = {
75
+ "A.6.1.1": {
76
+ "name": "Information security roles and responsibilities",
77
+ "org_attributes": ["organizational_units", "account_tags", "scp_policies"],
78
+ },
79
+ "A.6.1.2": {
80
+ "name": "Segregation of duties",
81
+ "org_attributes": ["organizational_structure", "scp_enforcement", "account_separation"],
82
+ },
83
+ }
84
+
85
+ # SCP patterns that indicate good security posture
86
+ RESTRICTIVE_SCP_PATTERNS = [
87
+ "DenyAllOutsideRegion",
88
+ "RestrictRegions",
89
+ "DenyRootAccount",
90
+ "RequireMFA",
91
+ "DenyLeaveOrganization",
92
+ "PreventSCPRemoval",
93
+ "DenyCloudTrailDelete",
94
+ "DenyGuardDutyDisable",
95
+ "DenyConfigDisable",
96
+ ]
97
+
98
+ # Account statuses that are compliant
99
+ COMPLIANT_ACCOUNT_STATUSES = ["ACTIVE"]
100
+
101
+
102
+ class OrgControlMapper:
103
+ """Map AWS Organizations attributes to compliance control status."""
104
+
105
+ def __init__(self, framework: str = "NIST800-53R5"):
106
+ """
107
+ Initialize Organizations control mapper.
108
+
109
+ :param str framework: Compliance framework (NIST800-53R5 or ISO27001)
110
+ """
111
+ self.framework = framework
112
+ self.mappings = ORG_CONTROL_MAPPINGS if framework == "NIST800-53R5" else ISO_27001_MAPPINGS
113
+
114
+ def assess_organization_compliance(self, org_data: Dict) -> Dict[str, str]:
115
+ """
116
+ Assess AWS Organizations compliance against all mapped controls.
117
+
118
+ :param Dict org_data: Organization structure and metadata
119
+ :return: Dictionary mapping control IDs to compliance results (PASS/FAIL)
120
+ :rtype: Dict[str, str]
121
+ """
122
+ results = {}
123
+
124
+ if self.framework == "NIST800-53R5":
125
+ results["AC-1"] = self._assess_ac1(org_data)
126
+ results["PM-9"] = self._assess_pm9(org_data)
127
+ results["AC-2"] = self._assess_ac2(org_data)
128
+ results["AC-6"] = self._assess_ac6(org_data)
129
+
130
+ return results
131
+
132
+ def _assess_ac1(self, org_data: Dict) -> str:
133
+ """
134
+ Assess AC-1 (Access Control Policy and Procedures) compliance.
135
+
136
+ :param Dict org_data: Organization data
137
+ :return: Compliance result (PASS/FAIL)
138
+ :rtype: str
139
+ """
140
+ scps = org_data.get("service_control_policies", [])
141
+ ous = org_data.get("organizational_units", [])
142
+
143
+ # Check if organization has SCPs beyond default FullAWSAccess
144
+ restrictive_scps = [scp for scp in scps if scp.get("Name") != "FullAWSAccess"]
145
+
146
+ if not restrictive_scps:
147
+ logger.debug("Organization FAILS AC-1: No restrictive SCPs attached")
148
+ return "FAIL"
149
+
150
+ # Check for organizational structure (OUs)
151
+ if len(ous) < 2: # Should have at least root + 1 OU
152
+ logger.debug("Organization FAILS AC-1: No organizational structure (only root OU)")
153
+ return "FAIL"
154
+
155
+ logger.debug(f"Organization PASSES AC-1: {len(restrictive_scps)} restrictive SCPs, {len(ous)} OUs")
156
+ return "PASS"
157
+
158
+ def _assess_pm9(self, org_data: Dict) -> str:
159
+ """
160
+ Assess PM-9 (Risk Management Strategy) compliance.
161
+
162
+ :param Dict org_data: Organization data
163
+ :return: Compliance result (PASS/FAIL)
164
+ :rtype: str
165
+ """
166
+ ous = org_data.get("organizational_units", [])
167
+ scps = org_data.get("service_control_policies", [])
168
+
169
+ # Check for risk-based OU structure (prod, dev, sandbox, etc.)
170
+ ou_names = [ou.get("Name", "").lower() for ou in ous]
171
+ has_env_separation = any(
172
+ env in " ".join(ou_names) for env in ["prod", "production", "dev", "development", "sandbox", "test"]
173
+ )
174
+
175
+ if not has_env_separation:
176
+ logger.debug("Organization FAILS PM-9: No environment-based OU separation")
177
+ return "FAIL"
178
+
179
+ # Check for restrictive SCPs
180
+ has_restrictive_scps = any(
181
+ any(pattern.lower() in scp.get("Name", "").lower() for pattern in RESTRICTIVE_SCP_PATTERNS) for scp in scps
182
+ )
183
+
184
+ if not has_restrictive_scps:
185
+ logger.debug("Organization FAILS PM-9: No restrictive SCPs enforcing security guardrails")
186
+ return "FAIL"
187
+
188
+ logger.debug("Organization PASSES PM-9: Environment separation and restrictive SCPs present")
189
+ return "PASS"
190
+
191
+ def _assess_ac2(self, org_data: Dict) -> str:
192
+ """
193
+ Assess AC-2 (Account Management) compliance.
194
+
195
+ :param Dict org_data: Organization data
196
+ :return: Compliance result (PASS/FAIL)
197
+ :rtype: str
198
+ """
199
+ accounts = org_data.get("accounts", [])
200
+
201
+ if not accounts:
202
+ logger.debug("Organization FAILS AC-2: No accounts found")
203
+ return "FAIL"
204
+
205
+ # Check account statuses
206
+ non_active_accounts = [acc for acc in accounts if acc.get("Status") not in COMPLIANT_ACCOUNT_STATUSES]
207
+
208
+ if non_active_accounts:
209
+ logger.debug(f"Organization FAILS AC-2: {len(non_active_accounts)} accounts not in ACTIVE status")
210
+ return "FAIL"
211
+
212
+ # Check for accounts missing email
213
+ accounts_missing_email = [acc for acc in accounts if not acc.get("Email")]
214
+
215
+ if accounts_missing_email:
216
+ logger.debug(f"Organization FAILS AC-2: {len(accounts_missing_email)} accounts missing contact email")
217
+ return "FAIL"
218
+
219
+ logger.debug(f"Organization PASSES AC-2: All {len(accounts)} accounts are ACTIVE with contact info")
220
+ return "PASS"
221
+
222
+ def _assess_ac6(self, org_data: Dict) -> str:
223
+ """
224
+ Assess AC-6 (Least Privilege) compliance.
225
+
226
+ :param Dict org_data: Organization data
227
+ :return: Compliance result (PASS/FAIL)
228
+ :rtype: str
229
+ """
230
+ scps = org_data.get("service_control_policies", [])
231
+
232
+ # Check if only FullAWSAccess is attached (not least privilege)
233
+ only_full_access = len(scps) == 1 and scps[0].get("Name") == "FullAWSAccess"
234
+
235
+ if only_full_access:
236
+ logger.debug("Organization FAILS AC-6: Only FullAWSAccess SCP attached (not least privilege)")
237
+ return "FAIL"
238
+
239
+ # Check for at least one restrictive SCP
240
+ has_restrictive = any(
241
+ any(pattern.lower() in scp.get("Name", "").lower() for pattern in RESTRICTIVE_SCP_PATTERNS)
242
+ or "Deny" in scp.get("Name", "")
243
+ for scp in scps
244
+ )
245
+
246
+ if not has_restrictive:
247
+ logger.debug("Organization FAILS AC-6: No restrictive/deny SCPs implementing least privilege")
248
+ return "FAIL"
249
+
250
+ logger.debug("Organization PASSES AC-6: Restrictive SCPs implementing least privilege")
251
+ return "PASS"
252
+
253
+ def get_control_description(self, control_id: str) -> Optional[str]:
254
+ """
255
+ Get human-readable description for a control.
256
+
257
+ :param str control_id: Control identifier (e.g., AC-1)
258
+ :return: Control description or None
259
+ :rtype: Optional[str]
260
+ """
261
+ control_data = self.mappings.get(control_id)
262
+ if control_data:
263
+ return f"{control_data.get('name')}: {control_data.get('description', '')}"
264
+ return None
265
+
266
+ def get_mapped_controls(self) -> List[str]:
267
+ """
268
+ Get list of all control IDs mapped for this framework.
269
+
270
+ :return: List of control IDs
271
+ :rtype: List[str]
272
+ """
273
+ return list(self.mappings.keys())
274
+
275
+ def get_check_details(self, control_id: str) -> Optional[Dict]:
276
+ """
277
+ Get detailed check criteria for a control.
278
+
279
+ :param str control_id: Control identifier
280
+ :return: Dictionary of check details or None
281
+ :rtype: Optional[Dict]
282
+ """
283
+ control_data = self.mappings.get(control_id)
284
+ if control_data:
285
+ return control_data.get("checks", {})
286
+ return None