regscale-cli 6.27.3.0__py3-none-any.whl → 6.28.1.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 (113) hide show
  1. regscale/_version.py +1 -1
  2. regscale/core/app/utils/app_utils.py +11 -2
  3. regscale/dev/cli.py +26 -0
  4. regscale/dev/version.py +72 -0
  5. regscale/integrations/commercial/__init__.py +15 -1
  6. regscale/integrations/commercial/amazon/amazon/__init__.py +0 -0
  7. regscale/integrations/commercial/amazon/amazon/common.py +204 -0
  8. regscale/integrations/commercial/amazon/common.py +48 -58
  9. regscale/integrations/commercial/aws/audit_manager_compliance.py +2671 -0
  10. regscale/integrations/commercial/aws/cli.py +3093 -55
  11. regscale/integrations/commercial/aws/cloudtrail_control_mappings.py +333 -0
  12. regscale/integrations/commercial/aws/cloudtrail_evidence.py +501 -0
  13. regscale/integrations/commercial/aws/cloudwatch_control_mappings.py +357 -0
  14. regscale/integrations/commercial/aws/cloudwatch_evidence.py +490 -0
  15. regscale/integrations/commercial/aws/config_compliance.py +914 -0
  16. regscale/integrations/commercial/aws/conformance_pack_mappings.py +198 -0
  17. regscale/integrations/commercial/aws/evidence_generator.py +283 -0
  18. regscale/integrations/commercial/aws/guardduty_control_mappings.py +340 -0
  19. regscale/integrations/commercial/aws/guardduty_evidence.py +1053 -0
  20. regscale/integrations/commercial/aws/iam_control_mappings.py +368 -0
  21. regscale/integrations/commercial/aws/iam_evidence.py +574 -0
  22. regscale/integrations/commercial/aws/inventory/__init__.py +223 -22
  23. regscale/integrations/commercial/aws/inventory/base.py +107 -5
  24. regscale/integrations/commercial/aws/inventory/resources/audit_manager.py +513 -0
  25. regscale/integrations/commercial/aws/inventory/resources/cloudtrail.py +315 -0
  26. regscale/integrations/commercial/aws/inventory/resources/cloudtrail_logs_metadata.py +476 -0
  27. regscale/integrations/commercial/aws/inventory/resources/cloudwatch.py +191 -0
  28. regscale/integrations/commercial/aws/inventory/resources/compute.py +66 -9
  29. regscale/integrations/commercial/aws/inventory/resources/config.py +464 -0
  30. regscale/integrations/commercial/aws/inventory/resources/containers.py +74 -9
  31. regscale/integrations/commercial/aws/inventory/resources/database.py +106 -31
  32. regscale/integrations/commercial/aws/inventory/resources/guardduty.py +286 -0
  33. regscale/integrations/commercial/aws/inventory/resources/iam.py +470 -0
  34. regscale/integrations/commercial/aws/inventory/resources/inspector.py +476 -0
  35. regscale/integrations/commercial/aws/inventory/resources/integration.py +175 -61
  36. regscale/integrations/commercial/aws/inventory/resources/kms.py +447 -0
  37. regscale/integrations/commercial/aws/inventory/resources/networking.py +103 -67
  38. regscale/integrations/commercial/aws/inventory/resources/s3.py +394 -0
  39. regscale/integrations/commercial/aws/inventory/resources/security.py +268 -72
  40. regscale/integrations/commercial/aws/inventory/resources/securityhub.py +473 -0
  41. regscale/integrations/commercial/aws/inventory/resources/storage.py +53 -29
  42. regscale/integrations/commercial/aws/inventory/resources/systems_manager.py +657 -0
  43. regscale/integrations/commercial/aws/inventory/resources/vpc.py +655 -0
  44. regscale/integrations/commercial/aws/kms_control_mappings.py +288 -0
  45. regscale/integrations/commercial/aws/kms_evidence.py +879 -0
  46. regscale/integrations/commercial/aws/ocsf/__init__.py +7 -0
  47. regscale/integrations/commercial/aws/ocsf/constants.py +115 -0
  48. regscale/integrations/commercial/aws/ocsf/mapper.py +435 -0
  49. regscale/integrations/commercial/aws/org_control_mappings.py +286 -0
  50. regscale/integrations/commercial/aws/org_evidence.py +666 -0
  51. regscale/integrations/commercial/aws/s3_control_mappings.py +356 -0
  52. regscale/integrations/commercial/aws/s3_evidence.py +632 -0
  53. regscale/integrations/commercial/aws/scanner.py +851 -206
  54. regscale/integrations/commercial/aws/security_hub.py +319 -0
  55. regscale/integrations/commercial/aws/session_manager.py +282 -0
  56. regscale/integrations/commercial/aws/ssm_control_mappings.py +291 -0
  57. regscale/integrations/commercial/aws/ssm_evidence.py +492 -0
  58. regscale/integrations/commercial/synqly/ticketing.py +27 -0
  59. regscale/integrations/compliance_integration.py +308 -38
  60. regscale/integrations/due_date_handler.py +3 -0
  61. regscale/integrations/scanner_integration.py +399 -84
  62. regscale/models/integration_models/cisa_kev_data.json +65 -5
  63. regscale/models/integration_models/synqly_models/capabilities.json +1 -1
  64. regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +17 -9
  65. regscale/models/regscale_models/assessment.py +2 -1
  66. regscale/models/regscale_models/control_objective.py +74 -5
  67. regscale/models/regscale_models/file.py +2 -0
  68. regscale/models/regscale_models/issue.py +2 -5
  69. {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/METADATA +1 -1
  70. {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/RECORD +113 -34
  71. tests/regscale/integrations/commercial/aws/__init__.py +0 -0
  72. tests/regscale/integrations/commercial/aws/test_audit_manager_compliance.py +1304 -0
  73. tests/regscale/integrations/commercial/aws/test_audit_manager_evidence_aggregation.py +341 -0
  74. tests/regscale/integrations/commercial/aws/test_aws_audit_manager_collector.py +1155 -0
  75. tests/regscale/integrations/commercial/aws/test_aws_cloudtrail_collector.py +534 -0
  76. tests/regscale/integrations/commercial/aws/test_aws_config_collector.py +400 -0
  77. tests/regscale/integrations/commercial/aws/test_aws_guardduty_collector.py +315 -0
  78. tests/regscale/integrations/commercial/aws/test_aws_iam_collector.py +458 -0
  79. tests/regscale/integrations/commercial/aws/test_aws_inspector_collector.py +353 -0
  80. tests/regscale/integrations/commercial/aws/test_aws_inventory_integration.py +530 -0
  81. tests/regscale/integrations/commercial/aws/test_aws_kms_collector.py +919 -0
  82. tests/regscale/integrations/commercial/aws/test_aws_s3_collector.py +722 -0
  83. tests/regscale/integrations/commercial/aws/test_aws_scanner_integration.py +722 -0
  84. tests/regscale/integrations/commercial/aws/test_aws_securityhub_collector.py +792 -0
  85. tests/regscale/integrations/commercial/aws/test_aws_systems_manager_collector.py +918 -0
  86. tests/regscale/integrations/commercial/aws/test_aws_vpc_collector.py +996 -0
  87. tests/regscale/integrations/commercial/aws/test_cli_evidence.py +431 -0
  88. tests/regscale/integrations/commercial/aws/test_cloudtrail_control_mappings.py +452 -0
  89. tests/regscale/integrations/commercial/aws/test_cloudtrail_evidence.py +788 -0
  90. tests/regscale/integrations/commercial/aws/test_config_compliance.py +298 -0
  91. tests/regscale/integrations/commercial/aws/test_conformance_pack_mappings.py +200 -0
  92. tests/regscale/integrations/commercial/aws/test_evidence_generator.py +386 -0
  93. tests/regscale/integrations/commercial/aws/test_guardduty_control_mappings.py +564 -0
  94. tests/regscale/integrations/commercial/aws/test_guardduty_evidence.py +1041 -0
  95. tests/regscale/integrations/commercial/aws/test_iam_control_mappings.py +718 -0
  96. tests/regscale/integrations/commercial/aws/test_iam_evidence.py +1375 -0
  97. tests/regscale/integrations/commercial/aws/test_kms_control_mappings.py +656 -0
  98. tests/regscale/integrations/commercial/aws/test_kms_evidence.py +1163 -0
  99. tests/regscale/integrations/commercial/aws/test_ocsf_mapper.py +370 -0
  100. tests/regscale/integrations/commercial/aws/test_org_control_mappings.py +546 -0
  101. tests/regscale/integrations/commercial/aws/test_org_evidence.py +1240 -0
  102. tests/regscale/integrations/commercial/aws/test_s3_control_mappings.py +672 -0
  103. tests/regscale/integrations/commercial/aws/test_s3_evidence.py +987 -0
  104. tests/regscale/integrations/commercial/aws/test_scanner_evidence.py +373 -0
  105. tests/regscale/integrations/commercial/aws/test_security_hub_config_filtering.py +539 -0
  106. tests/regscale/integrations/commercial/aws/test_session_manager.py +516 -0
  107. tests/regscale/integrations/commercial/aws/test_ssm_control_mappings.py +588 -0
  108. tests/regscale/integrations/commercial/aws/test_ssm_evidence.py +735 -0
  109. tests/regscale/integrations/commercial/test_aws.py +55 -56
  110. {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/LICENSE +0 -0
  111. {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/WHEEL +0 -0
  112. {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/entry_points.txt +0 -0
  113. {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/top_level.txt +0 -0
@@ -29,6 +29,7 @@ class TestAws(CLITestFixture):
29
29
  "InstanceType": instance_type,
30
30
  "State": state,
31
31
  "Region": "us-east-1",
32
+ "OwnerId": "123456789012",
32
33
  "CpuOptions": {"CoreCount": 2, "ThreadsPerCore": 1},
33
34
  "BlockDeviceMappings": [{"DeviceName": "/dev/xvda", "Ebs": {"VolumeId": "vol-12345678"}}],
34
35
  "ImageInfo": {
@@ -56,6 +57,11 @@ class TestAws(CLITestFixture):
56
57
  mock_self.num_assets_to_process = 0
57
58
  return mock_self
58
59
 
60
+ @pytest.fixture
61
+ def aws_integration(self):
62
+ """Create a real AWSInventoryIntegration instance for parser tests."""
63
+ return AWSInventoryIntegration(plan_id=1)
64
+
59
65
  @patch("regscale.integrations.commercial.aws.scanner.json.load")
60
66
  @patch("regscale.integrations.commercial.aws.scanner.os.path.exists", return_value=True)
61
67
  @patch("regscale.integrations.commercial.aws.scanner.os.path.getmtime")
@@ -112,7 +118,9 @@ class TestAws(CLITestFixture):
112
118
  )
113
119
 
114
120
  assert result == fresh_data
115
- mock_aws_integration.authenticate.assert_called_once_with("test_key", "test_secret", "us-east-1", None)
121
+ mock_aws_integration.authenticate.assert_called_once_with(
122
+ "test_key", "test_secret", "us-east-1", None, None, None, None
123
+ )
116
124
  mock_collector.collect_all.assert_called_once()
117
125
  mock_makedirs.assert_called_once()
118
126
  mock_json_dump.assert_called_once()
@@ -162,17 +170,14 @@ class TestAws(CLITestFixture):
162
170
  assert len(results) == 2
163
171
  assert results[0].name == "Asset 1"
164
172
  assert results[1].name == "Asset 2"
165
- assert mock_aws_integration.num_assets_to_process == 2
166
173
  assert mock_parser.call_count == 2
167
174
 
168
175
  def test_processes_special_users_structure(self, mock_aws_integration):
169
176
  """Should process special Users structure correctly."""
170
- assets = {
171
- "Users": [
172
- {"id": "user1", "name": "User 1"},
173
- {"id": "user2", "name": "User 2"},
174
- ]
175
- }
177
+ assets = [
178
+ {"id": "user1", "name": "User 1"},
179
+ {"id": "user2", "name": "User 2"},
180
+ ]
176
181
  asset_type = "IAM Users"
177
182
 
178
183
  mock_parser = MagicMock()
@@ -188,17 +193,14 @@ class TestAws(CLITestFixture):
188
193
  assert len(results) == 2
189
194
  assert results[0].name == "User 1"
190
195
  assert results[1].name == "User 2"
191
- assert mock_aws_integration.num_assets_to_process == 2
192
196
  assert mock_parser.call_count == 2
193
197
 
194
198
  def test_process_asset_collection_roles_special_case(self, mock_aws_integration):
195
199
  """Test processing special 'Roles' case"""
196
- assets = {
197
- "Roles": [
198
- {"id": "role1", "name": "Role 1"},
199
- {"id": "role2", "name": "Role 2"},
200
- ]
201
- }
200
+ assets = [
201
+ {"id": "role1", "name": "Role 1"},
202
+ {"id": "role2", "name": "Role 2"},
203
+ ]
202
204
  asset_type = "IAM Roles"
203
205
 
204
206
  mock_parser = MagicMock()
@@ -214,7 +216,6 @@ class TestAws(CLITestFixture):
214
216
  assert len(results) == 2
215
217
  assert results[0].name == "Role 1"
216
218
  assert results[1].name == "Role 2"
217
- assert mock_aws_integration.num_assets_to_process == 2
218
219
  assert mock_parser.call_count == 2
219
220
 
220
221
  def test_skips_invalid_asset_format(self, mock_aws_integration):
@@ -234,7 +235,6 @@ class TestAws(CLITestFixture):
234
235
 
235
236
  assert len(results) == 1
236
237
  assert results[0].name == "Valid Asset"
237
- assert mock_aws_integration.num_assets_to_process == 1
238
238
  assert mock_parser.call_count == 1
239
239
 
240
240
  def test_process_asset_collection_parser_exception(self, mock_aws_integration):
@@ -265,7 +265,6 @@ class TestAws(CLITestFixture):
265
265
 
266
266
  assert len(results) == 1
267
267
  assert results[0].name == "Asset 1"
268
- assert mock_aws_integration.num_assets_to_process == 2 # Counter still increments
269
268
  assert mock_parser.call_count == 2
270
269
 
271
270
  def test_process_asset_collection_empty_list(self, mock_aws_integration):
@@ -280,7 +279,6 @@ class TestAws(CLITestFixture):
280
279
  )
281
280
 
282
281
  assert len(results) == 0
283
- assert mock_aws_integration.num_assets_to_process == 0
284
282
  assert mock_parser.call_count == 0
285
283
 
286
284
  def test_process_asset_collection_mixed_valid_invalid(self, mock_aws_integration):
@@ -309,7 +307,6 @@ class TestAws(CLITestFixture):
309
307
  assert results[0].name == "Valid 1"
310
308
  assert results[1].name == "Valid 2"
311
309
  assert results[2].name == "Valid 3"
312
- assert mock_aws_integration.num_assets_to_process == 3
313
310
  assert mock_parser.call_count == 3
314
311
 
315
312
  def test_process_asset_collection_empty_users_roles(self, mock_aws_integration):
@@ -326,7 +323,6 @@ class TestAws(CLITestFixture):
326
323
  )
327
324
 
328
325
  assert len(results) == 0
329
- assert mock_aws_integration.num_assets_to_process == 0
330
326
  assert mock_parser.call_count == 0
331
327
 
332
328
  mock_aws_integration.num_assets_to_process = 0
@@ -341,7 +337,6 @@ class TestAws(CLITestFixture):
341
337
  )
342
338
 
343
339
  assert len(results) == 0
344
- assert mock_aws_integration.num_assets_to_process == 0
345
340
  assert mock_parser.call_count == 0
346
341
 
347
342
  def test_process_inventory_section_normal_processing(self, mock_aws_integration):
@@ -529,9 +524,9 @@ class TestAws(CLITestFixture):
529
524
  )
530
525
  )
531
526
 
532
- mock_aws_integration._process_asset_collection.assert_called_once_with(
533
- inventory["IAM"], asset_type, mock_parser
534
- )
527
+ # The implementation extracts the list from the IAM dict using asset_type as key
528
+ # Since asset_type is "IAM Users" but the dict has "Users", it returns []
529
+ mock_aws_integration._process_asset_collection.assert_called_once_with([], asset_type, mock_parser)
535
530
 
536
531
  assert len(results) == 2
537
532
  assert results[0].name == "User 1"
@@ -626,7 +621,7 @@ class TestAws(CLITestFixture):
626
621
  )
627
622
 
628
623
  mock_aws_integration.fetch_aws_data_if_needed.assert_called_once_with(
629
- "us-east-1", "test_key", "test_secret", "test_token"
624
+ "us-east-1", "test_key", "test_secret", "test_token", None, None, None, False
630
625
  )
631
626
 
632
627
  mock_aws_integration.get_asset_configs.assert_called_once()
@@ -658,7 +653,9 @@ class TestAws(CLITestFixture):
658
653
 
659
654
  results = list(AWSInventoryIntegration.fetch_assets(mock_aws_integration, region="us-east-1"))
660
655
 
661
- mock_aws_integration.fetch_aws_data_if_needed.assert_called_once_with("us-east-1", None, None, None)
656
+ mock_aws_integration.fetch_aws_data_if_needed.assert_called_once_with(
657
+ "us-east-1", None, None, None, None, None, None, False
658
+ )
662
659
 
663
660
  assert mock_aws_integration._process_inventory_section.call_count == 2
664
661
 
@@ -788,7 +785,7 @@ class TestAws(CLITestFixture):
788
785
  )
789
786
 
790
787
  mock_aws_integration.fetch_aws_data_if_needed.assert_called_once_with(
791
- "us-east-1", "test_key", "test_secret", None
788
+ "us-east-1", "test_key", "test_secret", None, None, None, None, False
792
789
  )
793
790
 
794
791
  mock_aws_integration.get_asset_configs.assert_called_once()
@@ -802,7 +799,7 @@ class TestAws(CLITestFixture):
802
799
  assert len(results) == 1
803
800
  assert results[0].name == "Test Instance"
804
801
 
805
- def test_parses_linux_instance_with_name_tag(self, mock_aws_integration):
802
+ def test_parses_linux_instance_with_name_tag(self, aws_integration):
806
803
  """Should parse Linux EC2 instance with Name tag correctly."""
807
804
  instance = self._build_ec2_instance_data(
808
805
  instance_id="i-1234567890abcdef0",
@@ -820,7 +817,7 @@ class TestAws(CLITestFixture):
820
817
  Tags=[{"Key": "Name", "Value": "Test Linux Server"}, {"Key": "Environment", "Value": "Production"}],
821
818
  )
822
819
 
823
- result = AWSInventoryIntegration.parse_ec2_instance(mock_aws_integration, instance)
820
+ result = aws_integration.parse_ec2_instance(instance)
824
821
 
825
822
  assert result.name == "Test Linux Server"
826
823
  assert result.identifier == "i-1234567890abcdef0"
@@ -843,7 +840,7 @@ class TestAws(CLITestFixture):
843
840
  )
844
841
  assert result.uri == expected_uri
845
842
 
846
- def test_parses_windows_instance(self, mock_aws_integration):
843
+ def test_parses_windows_instance(self, aws_integration):
847
844
  """Should parse Windows EC2 instance correctly."""
848
845
  instance = self._build_ec2_instance_data(
849
846
  instance_id="i-0987654321fedcba0",
@@ -865,7 +862,7 @@ class TestAws(CLITestFixture):
865
862
  },
866
863
  )
867
864
 
868
- result = AWSInventoryIntegration.parse_ec2_instance(mock_aws_integration, instance)
865
+ result = aws_integration.parse_ec2_instance(instance)
869
866
 
870
867
  assert result.operating_system == regscale_models.AssetOperatingSystem.WindowsServer
871
868
  assert result.asset_type == regscale_models.AssetType.VM
@@ -874,7 +871,7 @@ class TestAws(CLITestFixture):
874
871
  assert result.fqdn == "i-0987654321fedcba0" # No DNS names, falls back to instance ID
875
872
  assert "Windows" in result.description
876
873
 
877
- def test_parse_ec2_instance_palo_alto(self, mock_aws_integration):
874
+ def test_parse_ec2_instance_palo_alto(self, aws_integration):
878
875
  """Test parsing a Palo Alto EC2 instance"""
879
876
  instance = {
880
877
  "InstanceId": "i-paloalto123456",
@@ -892,7 +889,7 @@ class TestAws(CLITestFixture):
892
889
  },
893
890
  }
894
891
 
895
- result = AWSInventoryIntegration.parse_ec2_instance(mock_aws_integration, instance)
892
+ result = aws_integration.parse_ec2_instance(instance)
896
893
 
897
894
  assert result.operating_system == regscale_models.AssetOperatingSystem.PaloAlto
898
895
  assert result.asset_type == regscale_models.AssetType.Appliance
@@ -902,7 +899,7 @@ class TestAws(CLITestFixture):
902
899
  assert result.cpu == 2 # 2 cores * 1 thread
903
900
  assert "Palo Alto Networks VM-Series Firewall" in result.os_version
904
901
 
905
- def test_parse_ec2_instance_no_name_tag(self, mock_aws_integration):
902
+ def test_parse_ec2_instance_no_name_tag(self, aws_integration):
906
903
  """Test parsing an EC2 instance without a Name tag"""
907
904
  instance = {
908
905
  "InstanceId": "i-noname123456",
@@ -921,14 +918,14 @@ class TestAws(CLITestFixture):
921
918
  },
922
919
  }
923
920
 
924
- result = AWSInventoryIntegration.parse_ec2_instance(mock_aws_integration, instance)
921
+ result = aws_integration.parse_ec2_instance(instance)
925
922
 
926
923
  assert result.name == "i-noname123456"
927
924
  assert result.status == regscale_models.AssetStatus.Inactive # stopped state
928
925
  assert result.cpu == 1 # 1 core * 1 thread
929
926
  assert result.disk_storage == 0 # No block devices
930
927
 
931
- def test_parse_ec2_instance_no_tags(self, mock_aws_integration):
928
+ def test_parse_ec2_instance_no_tags(self, aws_integration):
932
929
  """Test parsing an EC2 instance with no tags"""
933
930
  instance = {
934
931
  "InstanceId": "i-notags123456",
@@ -945,13 +942,13 @@ class TestAws(CLITestFixture):
945
942
  },
946
943
  }
947
944
 
948
- result = AWSInventoryIntegration.parse_ec2_instance(mock_aws_integration, instance)
945
+ result = aws_integration.parse_ec2_instance(instance)
949
946
 
950
947
  assert result.name == "i-notags123456"
951
948
  assert result.cpu == 2 # 2 cores * 1 thread
952
949
  assert result.disk_storage == 8 # 1 device * 8GB
953
950
 
954
- def test_parse_ec2_instance_public_facing(self, mock_aws_integration):
951
+ def test_parse_ec2_instance_public_facing(self, aws_integration):
955
952
  """Test parsing a public-facing EC2 instance"""
956
953
  instance = {
957
954
  "InstanceId": "i-public123456",
@@ -972,14 +969,14 @@ class TestAws(CLITestFixture):
972
969
  },
973
970
  }
974
971
 
975
- result = AWSInventoryIntegration.parse_ec2_instance(mock_aws_integration, instance)
972
+ result = aws_integration.parse_ec2_instance(instance)
976
973
 
977
974
  assert result.is_public_facing is True
978
975
  assert result.ip_address == "10.0.1.104" # Prefers private IP
979
976
  assert result.fqdn == "ec2-54-1-2-3.compute-1.amazonaws.com" # Prefers public DNS
980
977
  assert "Public IP: 54.1.2.3" in result.notes
981
978
 
982
- def test_parse_ec2_instance_private_only(self, mock_aws_integration):
979
+ def test_parse_ec2_instance_private_only(self, aws_integration):
983
980
  """Test parsing a private-only EC2 instance"""
984
981
  instance = {
985
982
  "InstanceId": "i-private123456",
@@ -998,14 +995,14 @@ class TestAws(CLITestFixture):
998
995
  },
999
996
  }
1000
997
 
1001
- result = AWSInventoryIntegration.parse_ec2_instance(mock_aws_integration, instance)
998
+ result = aws_integration.parse_ec2_instance(instance)
1002
999
 
1003
1000
  assert result.is_public_facing is False
1004
1001
  assert result.ip_address == "10.0.1.105"
1005
1002
  assert result.fqdn == "ip-10-0-1-105.ec2.internal"
1006
1003
  assert "Public IP: N/A" in result.notes
1007
1004
 
1008
- def test_parse_ec2_instance_minimal_data(self, mock_aws_integration):
1005
+ def test_parse_ec2_instance_minimal_data(self, aws_integration):
1009
1006
  """Test parsing an EC2 instance with minimal data"""
1010
1007
  instance = {
1011
1008
  "InstanceId": "i-minimal123456",
@@ -1014,7 +1011,7 @@ class TestAws(CLITestFixture):
1014
1011
  "Region": "us-east-1",
1015
1012
  }
1016
1013
 
1017
- result = AWSInventoryIntegration.parse_ec2_instance(mock_aws_integration, instance)
1014
+ result = aws_integration.parse_ec2_instance(instance)
1018
1015
 
1019
1016
  assert result.name == "i-minimal123456"
1020
1017
  assert result.identifier == "i-minimal123456"
@@ -1031,7 +1028,7 @@ class TestAws(CLITestFixture):
1031
1028
  assert "Private IP: N/A" in result.notes
1032
1029
  assert "Public IP: N/A" in result.notes
1033
1030
 
1034
- def test_parse_ec2_instance_edge_cases(self, mock_aws_integration):
1031
+ def test_parse_ec2_instance_edge_cases(self, aws_integration):
1035
1032
  """Test parsing EC2 instance with edge cases"""
1036
1033
  instance = {
1037
1034
  "InstanceId": "i-edge123456",
@@ -1051,7 +1048,7 @@ class TestAws(CLITestFixture):
1051
1048
  },
1052
1049
  }
1053
1050
 
1054
- result = AWSInventoryIntegration.parse_ec2_instance(mock_aws_integration, instance)
1051
+ result = aws_integration.parse_ec2_instance(instance)
1055
1052
 
1056
1053
  assert result.cpu == 0 # Empty CPU options
1057
1054
  assert result.disk_storage == 8 # Only one Ebs device
@@ -2172,6 +2169,7 @@ class TestAws(CLITestFixture):
2172
2169
  "CidrBlock": "10.0.0.0/16",
2173
2170
  "State": "available",
2174
2171
  "Region": "us-east-1",
2172
+ "OwnerId": "123456789012",
2175
2173
  "Tags": [{"Key": "Name", "Value": "Production VPC"}, {"Key": "Environment", "Value": "Production"}],
2176
2174
  }
2177
2175
 
@@ -2189,7 +2187,7 @@ class TestAws(CLITestFixture):
2189
2187
  assert result.location == "us-east-1"
2190
2188
  assert result.vlan_id == "vpc-12345678"
2191
2189
  assert result.external_id == "vpc-12345678"
2192
- assert result.aws_identifier == "vpc-12345678"
2190
+ assert result.aws_identifier == "arn:aws:ec2:us-east-1:123456789012:vpc/vpc-12345678"
2193
2191
  assert result.manufacturer == "AWS"
2194
2192
  assert result.notes == "CIDR: 10.0.0.0/16"
2195
2193
  assert result.source_data == vpc
@@ -2294,7 +2292,7 @@ class TestAws(CLITestFixture):
2294
2292
  result = AWSInventoryIntegration.parse_vpc(mock_aws_integration, vpc)
2295
2293
 
2296
2294
  assert result.name == "No Region VPC"
2297
- assert result.location is None
2295
+ assert result.location == "us-east-1" # Default region when not provided
2298
2296
  assert result.status == regscale_models.AssetStatus.Active
2299
2297
  assert result.notes == "CIDR: 10.0.0.0/16"
2300
2298
 
@@ -2312,9 +2310,9 @@ class TestAws(CLITestFixture):
2312
2310
 
2313
2311
  assert result.name == "No VPC ID"
2314
2312
  assert result.identifier == ""
2315
- assert result.vlan_id is None
2316
- assert result.external_id is None
2317
- assert result.aws_identifier is None
2313
+ assert result.vlan_id == "" # Empty string, not None
2314
+ assert result.external_id == "" # Empty string, not None
2315
+ assert result.aws_identifier == "arn:aws:ec2:us-east-1::vpc/" # ARN with empty VPC ID
2318
2316
  assert result.status == regscale_models.AssetStatus.Active
2319
2317
  assert result.location == "us-east-1"
2320
2318
  assert result.notes == "CIDR: 10.0.0.0/16"
@@ -2335,10 +2333,10 @@ class TestAws(CLITestFixture):
2335
2333
  assert result.parent_id == mock_aws_integration.plan_id
2336
2334
  assert result.parent_module == "securityplans"
2337
2335
  assert result.status == regscale_models.AssetStatus.Inactive # No state provided
2338
- assert result.location is None
2339
- assert result.vlan_id is None
2340
- assert result.external_id is None
2341
- assert result.aws_identifier is None
2336
+ assert result.location == "us-east-1" # Default region
2337
+ assert result.vlan_id == "" # Empty string
2338
+ assert result.external_id == "" # Empty string
2339
+ assert result.aws_identifier == "arn:aws:ec2:us-east-1::vpc/" # ARN with empty VPC ID
2342
2340
  assert result.manufacturer == "AWS"
2343
2341
  assert result.notes == "CIDR: None"
2344
2342
  assert result.source_data == vpc
@@ -2351,6 +2349,7 @@ class TestAws(CLITestFixture):
2351
2349
  "CidrBlock": "10.0.0.0/8",
2352
2350
  "State": "available",
2353
2351
  "Region": "us-east-1",
2352
+ "OwnerId": "123456789012",
2354
2353
  "IsDefault": False,
2355
2354
  "Tags": [
2356
2355
  {"Key": "Name", "Value": "Edge Case VPC"},
@@ -2367,7 +2366,7 @@ class TestAws(CLITestFixture):
2367
2366
  assert result.location == "us-east-1"
2368
2367
  assert result.vlan_id == "vpc-edge123"
2369
2368
  assert result.external_id == "vpc-edge123"
2370
- assert result.aws_identifier == "vpc-edge123"
2369
+ assert result.aws_identifier == "arn:aws:ec2:us-east-1:123456789012:vpc/vpc-edge123"
2371
2370
  assert result.notes == "CIDR: 10.0.0.0/8" # No "Default VPC" prefix since IsDefault is False
2372
2371
  assert result.asset_type == regscale_models.AssetType.NetworkRouter
2373
2372
  assert result.asset_category == regscale_models.AssetCategory.Hardware