aws-inventory-manager 0.17.12__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.
Files changed (152) hide show
  1. aws_inventory_manager-0.17.12.dist-info/LICENSE +21 -0
  2. aws_inventory_manager-0.17.12.dist-info/METADATA +1292 -0
  3. aws_inventory_manager-0.17.12.dist-info/RECORD +152 -0
  4. aws_inventory_manager-0.17.12.dist-info/WHEEL +5 -0
  5. aws_inventory_manager-0.17.12.dist-info/entry_points.txt +2 -0
  6. aws_inventory_manager-0.17.12.dist-info/top_level.txt +1 -0
  7. src/__init__.py +3 -0
  8. src/aws/__init__.py +11 -0
  9. src/aws/client.py +128 -0
  10. src/aws/credentials.py +191 -0
  11. src/aws/rate_limiter.py +177 -0
  12. src/cli/__init__.py +12 -0
  13. src/cli/config.py +130 -0
  14. src/cli/main.py +4046 -0
  15. src/cloudtrail/__init__.py +5 -0
  16. src/cloudtrail/query.py +642 -0
  17. src/config_service/__init__.py +21 -0
  18. src/config_service/collector.py +346 -0
  19. src/config_service/detector.py +256 -0
  20. src/config_service/resource_type_mapping.py +328 -0
  21. src/cost/__init__.py +5 -0
  22. src/cost/analyzer.py +226 -0
  23. src/cost/explorer.py +209 -0
  24. src/cost/reporter.py +237 -0
  25. src/delta/__init__.py +5 -0
  26. src/delta/calculator.py +206 -0
  27. src/delta/differ.py +185 -0
  28. src/delta/formatters.py +272 -0
  29. src/delta/models.py +154 -0
  30. src/delta/reporter.py +234 -0
  31. src/matching/__init__.py +6 -0
  32. src/matching/config.py +52 -0
  33. src/matching/normalizer.py +450 -0
  34. src/matching/prompts.py +33 -0
  35. src/models/__init__.py +21 -0
  36. src/models/config_diff.py +135 -0
  37. src/models/cost_report.py +87 -0
  38. src/models/deletion_operation.py +104 -0
  39. src/models/deletion_record.py +97 -0
  40. src/models/delta_report.py +122 -0
  41. src/models/efs_resource.py +80 -0
  42. src/models/elasticache_resource.py +90 -0
  43. src/models/group.py +318 -0
  44. src/models/inventory.py +133 -0
  45. src/models/protection_rule.py +123 -0
  46. src/models/report.py +288 -0
  47. src/models/resource.py +111 -0
  48. src/models/security_finding.py +102 -0
  49. src/models/snapshot.py +122 -0
  50. src/restore/__init__.py +20 -0
  51. src/restore/audit.py +175 -0
  52. src/restore/cleaner.py +461 -0
  53. src/restore/config.py +209 -0
  54. src/restore/deleter.py +976 -0
  55. src/restore/dependency.py +254 -0
  56. src/restore/safety.py +115 -0
  57. src/security/__init__.py +0 -0
  58. src/security/checks/__init__.py +0 -0
  59. src/security/checks/base.py +56 -0
  60. src/security/checks/ec2_checks.py +88 -0
  61. src/security/checks/elasticache_checks.py +149 -0
  62. src/security/checks/iam_checks.py +102 -0
  63. src/security/checks/rds_checks.py +140 -0
  64. src/security/checks/s3_checks.py +95 -0
  65. src/security/checks/secrets_checks.py +96 -0
  66. src/security/checks/sg_checks.py +142 -0
  67. src/security/cis_mapper.py +97 -0
  68. src/security/models.py +53 -0
  69. src/security/reporter.py +174 -0
  70. src/security/scanner.py +87 -0
  71. src/snapshot/__init__.py +6 -0
  72. src/snapshot/capturer.py +453 -0
  73. src/snapshot/filter.py +259 -0
  74. src/snapshot/inventory_storage.py +236 -0
  75. src/snapshot/report_formatter.py +250 -0
  76. src/snapshot/reporter.py +189 -0
  77. src/snapshot/resource_collectors/__init__.py +5 -0
  78. src/snapshot/resource_collectors/apigateway.py +140 -0
  79. src/snapshot/resource_collectors/backup.py +136 -0
  80. src/snapshot/resource_collectors/base.py +81 -0
  81. src/snapshot/resource_collectors/cloudformation.py +55 -0
  82. src/snapshot/resource_collectors/cloudwatch.py +109 -0
  83. src/snapshot/resource_collectors/codebuild.py +69 -0
  84. src/snapshot/resource_collectors/codepipeline.py +82 -0
  85. src/snapshot/resource_collectors/dynamodb.py +65 -0
  86. src/snapshot/resource_collectors/ec2.py +240 -0
  87. src/snapshot/resource_collectors/ecs.py +215 -0
  88. src/snapshot/resource_collectors/efs_collector.py +102 -0
  89. src/snapshot/resource_collectors/eks.py +200 -0
  90. src/snapshot/resource_collectors/elasticache_collector.py +79 -0
  91. src/snapshot/resource_collectors/elb.py +126 -0
  92. src/snapshot/resource_collectors/eventbridge.py +156 -0
  93. src/snapshot/resource_collectors/glue.py +199 -0
  94. src/snapshot/resource_collectors/iam.py +188 -0
  95. src/snapshot/resource_collectors/kms.py +111 -0
  96. src/snapshot/resource_collectors/lambda_func.py +139 -0
  97. src/snapshot/resource_collectors/rds.py +109 -0
  98. src/snapshot/resource_collectors/route53.py +86 -0
  99. src/snapshot/resource_collectors/s3.py +105 -0
  100. src/snapshot/resource_collectors/secretsmanager.py +70 -0
  101. src/snapshot/resource_collectors/sns.py +68 -0
  102. src/snapshot/resource_collectors/sqs.py +82 -0
  103. src/snapshot/resource_collectors/ssm.py +160 -0
  104. src/snapshot/resource_collectors/stepfunctions.py +74 -0
  105. src/snapshot/resource_collectors/vpcendpoints.py +79 -0
  106. src/snapshot/resource_collectors/waf.py +159 -0
  107. src/snapshot/storage.py +351 -0
  108. src/storage/__init__.py +21 -0
  109. src/storage/audit_store.py +419 -0
  110. src/storage/database.py +294 -0
  111. src/storage/group_store.py +763 -0
  112. src/storage/inventory_store.py +320 -0
  113. src/storage/resource_store.py +416 -0
  114. src/storage/schema.py +339 -0
  115. src/storage/snapshot_store.py +363 -0
  116. src/utils/__init__.py +12 -0
  117. src/utils/export.py +305 -0
  118. src/utils/hash.py +60 -0
  119. src/utils/logging.py +63 -0
  120. src/utils/pagination.py +41 -0
  121. src/utils/paths.py +51 -0
  122. src/utils/progress.py +41 -0
  123. src/utils/unsupported_resources.py +306 -0
  124. src/web/__init__.py +5 -0
  125. src/web/app.py +97 -0
  126. src/web/dependencies.py +69 -0
  127. src/web/routes/__init__.py +1 -0
  128. src/web/routes/api/__init__.py +18 -0
  129. src/web/routes/api/charts.py +156 -0
  130. src/web/routes/api/cleanup.py +186 -0
  131. src/web/routes/api/filters.py +253 -0
  132. src/web/routes/api/groups.py +305 -0
  133. src/web/routes/api/inventories.py +80 -0
  134. src/web/routes/api/queries.py +202 -0
  135. src/web/routes/api/resources.py +393 -0
  136. src/web/routes/api/snapshots.py +314 -0
  137. src/web/routes/api/views.py +260 -0
  138. src/web/routes/pages.py +198 -0
  139. src/web/services/__init__.py +1 -0
  140. src/web/templates/base.html +955 -0
  141. src/web/templates/components/navbar.html +31 -0
  142. src/web/templates/components/sidebar.html +104 -0
  143. src/web/templates/pages/audit_logs.html +86 -0
  144. src/web/templates/pages/cleanup.html +279 -0
  145. src/web/templates/pages/dashboard.html +227 -0
  146. src/web/templates/pages/diff.html +175 -0
  147. src/web/templates/pages/error.html +30 -0
  148. src/web/templates/pages/groups.html +721 -0
  149. src/web/templates/pages/queries.html +246 -0
  150. src/web/templates/pages/resources.html +2429 -0
  151. src/web/templates/pages/snapshot_detail.html +271 -0
  152. src/web/templates/pages/snapshots.html +429 -0
@@ -0,0 +1,152 @@
1
+ src/__init__.py,sha256=DMK4jB1kbfaPjMeyFvozB7wOQmpsX41md4fINtVJsyk,75
2
+ src/aws/__init__.py,sha256=FcFY2cn8ZQCnActrZYH1hD0x4uFkM9bMBDOmuHA3_mw,253
3
+ src/aws/client.py,sha256=CjqCxEsbgxQYWx_HF6g9_W-pfXl7yr1Z9armXyzuYpM,4089
4
+ src/aws/credentials.py,sha256=mxj8lQf7TRG5dznQJ37rGQqfB-viHh_5VCt1C4xgqG0,6374
5
+ src/aws/rate_limiter.py,sha256=b3dV4A9ftUsGgVMOQmv3IVO0Fkym2o1QDHKpFOdSYbg,5464
6
+ src/cli/__init__.py,sha256=zstPcm000JdpuUuMRuqL2TkC-bnCpm0syHjAyu8ELcY,387
7
+ src/cli/config.py,sha256=to_hVDxQh0WNANPDQKYlnZzCsFS6_bnrE745wZgRQe4,4286
8
+ src/cli/main.py,sha256=kXD9CdOUPwD5-ZJThvOICFRN8l3NNxMwwhi8Pq4dypw,165369
9
+ src/cloudtrail/__init__.py,sha256=lFrH6WLbeJQ5fCfVdyxQrta3Mr_RYQAM4N-IwyazdZI,179
10
+ src/cloudtrail/query.py,sha256=mnxQhhY-po9gCCTam8dN5rxNxAkuj4-upOEFqTyS9aQ,22216
11
+ src/config_service/__init__.py,sha256=fqYfceBP_kPnp8PjYW9D_FqsWqrrOzsQTftBgp7-aTE,585
12
+ src/config_service/collector.py,sha256=uW6m1feceYCOgANGWvxhbw23etcaqSQpmdIu-DTsWuk,12254
13
+ src/config_service/detector.py,sha256=BoJC32DXN2f8x8U8RiOmjkGtnrTQrRuO568FHcMt_xU,8531
14
+ src/config_service/resource_type_mapping.py,sha256=DyxmPcP0vQ2ouZ0hRS-oXUcViSNYSfzwXYuvoUu8cu8,8726
15
+ src/cost/__init__.py,sha256=WpTwsWAm8wyCkB65gsCnzu89-r5G_hgrbL9zTqvQ8j8,122
16
+ src/cost/analyzer.py,sha256=02WFkZErD-zfu1Jp8UDym3wTjuB0c3l5jadZmbGbBJk,10201
17
+ src/cost/explorer.py,sha256=c4Yj7w5gmvoeD9iY7hseinj3Ij-g9Rh8YXWYZVkO6u4,6847
18
+ src/cost/reporter.py,sha256=JPisT4C8YIt3vaQ1wD4VOAsRu5STNhp5Grs0ugQ0zA4,9609
19
+ src/delta/__init__.py,sha256=ypHqn-VKswWWisVQC1sY_23VqHC_LIaSdQv6HIwYU4Y,120
20
+ src/delta/calculator.py,sha256=5KKUKYiCQdTtfqB84llwej52Ev0r9B5SZfJ4aNuq37E,7833
21
+ src/delta/differ.py,sha256=-7MESqWyO8srPhs9OlsLJjYx57qPwQRh93GsatqnoW8,6692
22
+ src/delta/formatters.py,sha256=xhzph_iLGLD8yyflYCMTFZqWPmW9tB7hZsVHsgQDrzM,9209
23
+ src/delta/models.py,sha256=_biiC136e-C2GljlIeW7ql5vC47Ss1M8a-jgw9K9rFg,5103
24
+ src/delta/reporter.py,sha256=yqzof9snkJyJiOeGoLAla2pmnFNIPlR3brg7xrstpNA,8775
25
+ src/matching/__init__.py,sha256=cidLzXlQo29bV0OXX7AC5A9OLcEStB0NHb61WeatDDo,239
26
+ src/matching/config.py,sha256=eUACdOEUMyEjFzEuKxx4TevcpTIyey555Oq11yV9_6U,1703
27
+ src/matching/normalizer.py,sha256=D_ZNU9U43byVtpLsTF7B6K6CayKjtQ4TKxkSpNzDwTs,15846
28
+ src/matching/prompts.py,sha256=2sqsWktMcygvgOLoHpMeNO1I7_JqprhmGlwzV9S-vz4,1678
29
+ src/models/__init__.py,sha256=5DFL_8ZgLE28EG8ORumMT3EfhFAxXrFa3yzQpQBSQxc,533
30
+ src/models/config_diff.py,sha256=elh4oUgoln_sDC6lmkqfSd8k1pX9oqBPqTEgTksw5f8,4237
31
+ src/models/cost_report.py,sha256=BzyWrMewHau7EpQyLm4WoesVY3WDPBOtGVdk_H8USuM,3079
32
+ src/models/deletion_operation.py,sha256=bb2TiY_UsHEBk-B6qp1_miXOePTphhIAWRMnhYrh3k8,3468
33
+ src/models/deletion_record.py,sha256=OxA3oDRKhGct_D0apaOBg5lPQqc5CdICswpXipCrnes,3311
34
+ src/models/delta_report.py,sha256=TD0Jk2I9D5Fw2oXEkN6oUwMzGeIVfQzsRY-LK_MR8to,4854
35
+ src/models/efs_resource.py,sha256=Jq8bzDKEYo8vB6M-Zz1RVowteD0nyxUhF8C6gumWe7E,2665
36
+ src/models/elasticache_resource.py,sha256=WRHOjZ7m4cT7OwfL8GQp5Ays9S8i9RLGynkAr5aAB3o,3201
37
+ src/models/group.py,sha256=suBBtO4ipRjZP1XptNfcMMkERcAtYTYf3YIkcYYRoeU,11452
38
+ src/models/inventory.py,sha256=hEg5qQy_K8HvgtM7AyU1y1MX6c9xzsOefbCShCaH8PI,5157
39
+ src/models/protection_rule.py,sha256=DjGJ6il9y6fPe5WTZzlq0BJwfAOyQf6vEwmT-SjDYsc,3929
40
+ src/models/report.py,sha256=Qb9OKdPNRFxcfxk-9vFEnVctKaVWgg4aP-QTEBgJlxo,9288
41
+ src/models/resource.py,sha256=jTpdJabrn0KRU6aGEiJZyUtZFTvXIDNgPDWx5MmIVZs,3882
42
+ src/models/security_finding.py,sha256=RyTobHFg6n0eomCDVuL89zYevpmSInneZ4RtDHtms9U,3451
43
+ src/models/snapshot.py,sha256=-kj9LYSrZSfSY44sc-TyJBNfjCYgegol8uCTXSJbNx8,4841
44
+ src/restore/__init__.py,sha256=iTghVKlfBxzzIxaun_AafOXHNLbyMwimJGtSwZZIyYY,563
45
+ src/restore/audit.py,sha256=XQH7iBrEFfSsewBesa677DZw1YXaqLqbvwByDq2vuTc,6538
46
+ src/restore/cleaner.py,sha256=o_4jeLgHIku54rKkiNNVowdVw5LY8UdxTT9ikQnnAx0,16589
47
+ src/restore/config.py,sha256=6MiqaIo_0x5V3F8XRKTvu24ij15IUiuQku39otySU7s,6536
48
+ src/restore/deleter.py,sha256=mqsg0w6vWeGBqVcvz82VjsHTeAltgS65Kevxv0eie_o,41483
49
+ src/restore/dependency.py,sha256=WNEgJAQHqpOF6ir9cjiUtGVbckQfRvToOWeJCtzR76U,9190
50
+ src/restore/safety.py,sha256=_LIlkcJdCJCXx9aopZuRrd18R8Ag-rv5G-xG20TOf14,3971
51
+ src/security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ src/security/cis_mapper.py,sha256=rLSQobH1a1fa_tc9nQpaOPGSx1Wt7vlomxSyyyNwdqI,3147
53
+ src/security/models.py,sha256=IASZUo9_35W3nwnehmpiW-X19WaJANYOpB_OUHEltHk,1579
54
+ src/security/reporter.py,sha256=oe84rm0-FRhUgIHERyozkWIJpg7LIA-TPsxG8FiZOGw,5543
55
+ src/security/scanner.py,sha256=JGWHYZJ2VHXzas6nvsqSlkd3PsU6dg6VnAfJZABmvEY,3293
56
+ src/security/checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
+ src/security/checks/base.py,sha256=2e-i55dVO-0N8squB6vUg5DEPZnTvW6XPpLPQLW5s0I,1371
58
+ src/security/checks/ec2_checks.py,sha256=hUO1cTN-zd45WEGy7xZIzb7LMOjdggTc8YfLyEVA38M,3113
59
+ src/security/checks/elasticache_checks.py,sha256=CGkF-6e5Z7iCKj3dvghyMsU9aF9abnLs7Xu7MPFvy4I,6108
60
+ src/security/checks/iam_checks.py,sha256=k-kSf4zmVZ7svrajt_-jPW5bDGyLrswAX2E9KhfqXbU,3952
61
+ src/security/checks/rds_checks.py,sha256=oRmflzwLf3_JeMEJt-pCoPKGFgwC2BdItzuUQYyyXEo,5112
62
+ src/security/checks/s3_checks.py,sha256=usHrGBmmIZc4PEDSMRRE1H8A_NwUxV2kiIVeLaPCauc,3387
63
+ src/security/checks/secrets_checks.py,sha256=2bJY0Hqb1PwUYid5XZCC6y4hgWle3sRtwYNVh4jmUBw,3631
64
+ src/security/checks/sg_checks.py,sha256=BmipY31beybajxSbS_HoDkSXFYTQFhjXWNxuYYPEP2U,4731
65
+ src/snapshot/__init__.py,sha256=trHfRe_8jxjQVb48cDLVH3gs2Y7YQtsX2gFL4OB9qRc,237
66
+ src/snapshot/capturer.py,sha256=5Pg3vITpsvr1r0J-wesUb7KnMLsAbxttd0EKsnF3K3Q,18046
67
+ src/snapshot/filter.py,sha256=UPVTi23NHJYKFTD4ss8PazDHh-NIC2lWLvjJnr9Y7QY,9158
68
+ src/snapshot/inventory_storage.py,sha256=eOwGzYhUrvnv_usgEaUF-0_cDGGf21k-vjRRKP7Z5Hs,7739
69
+ src/snapshot/report_formatter.py,sha256=WR7Adqq5FjJqu3iIWAnOZ9yp6AuJH1kA6uKKpT7jrT4,8266
70
+ src/snapshot/reporter.py,sha256=CZp5fj6RcHoD5a3-1unwq5KKIxrQA38rLWCjspnyvvI,6628
71
+ src/snapshot/storage.py,sha256=29zyNelW4QeH0C5E-GYnD5N4sQvyXtiZgPG8OYw4R7c,11826
72
+ src/snapshot/resource_collectors/__init__.py,sha256=QSJiStvbmqd_uCI6c4T03-3PMb0UmxAROZwVHPk25gc,94
73
+ src/snapshot/resource_collectors/apigateway.py,sha256=X916NdfRzUMNmMuyJdB_BrgTu1p7P7NwslPxWcPW4CU,4748
74
+ src/snapshot/resource_collectors/backup.py,sha256=mWySnU_47Se88uJN33scZovpUYPYwGRNMo3ur_yyqT0,4795
75
+ src/snapshot/resource_collectors/base.py,sha256=kpn0gRbf6PBb_1CA-0e6lnaI7jCm7mXPEsFwVNGSY-k,2369
76
+ src/snapshot/resource_collectors/cloudformation.py,sha256=YqMwzEF9neoXebRRfN0s8BT8ex66hWOPJQXk0aaLmxQ,1892
77
+ src/snapshot/resource_collectors/cloudwatch.py,sha256=JW4RMWl4hD_NTuAWtOV4v5FIPRY-opKuJeIecKxmzWI,4095
78
+ src/snapshot/resource_collectors/codebuild.py,sha256=VQjw-KSu4lA5kN7ci63vaphpPIgY4ZelYaFWTV7uD7M,2485
79
+ src/snapshot/resource_collectors/codepipeline.py,sha256=-1Dait_7Yzz-a_B9OtbsKNNzovbns0YKuFSifY0b5OU,3372
80
+ src/snapshot/resource_collectors/dynamodb.py,sha256=QRtEH5uLwrqF0yBIeHX_RLnOYovSnbcdTy6oo4xg9ZY,2463
81
+ src/snapshot/resource_collectors/ec2.py,sha256=hvor4Z0ofznR8sLvrK_OdvNh7-mvuDZeDOXPr1-X-qg,8441
82
+ src/snapshot/resource_collectors/ecs.py,sha256=90uj0FBU9uF03OZ7RkkS1Mc3g5YSz0v2hWYCOYS5NXw,8379
83
+ src/snapshot/resource_collectors/efs_collector.py,sha256=58ouqtCF16bxDO66-M1LojyVpJASyhv6D7RJ2KQC3DQ,4015
84
+ src/snapshot/resource_collectors/eks.py,sha256=T7Rh4ij3frxYgIfAcZNk0xNpoahwBfsQWcs14xcB5rE,7746
85
+ src/snapshot/resource_collectors/elasticache_collector.py,sha256=g7mVa9ZlE0DBITnA-i565REZRpumWMnqZuLVHcVO0Gw,2830
86
+ src/snapshot/resource_collectors/elb.py,sha256=af3IeKUv_FUfcLwYcnDajh4_4eSWtelvoazKCptehnQ,5125
87
+ src/snapshot/resource_collectors/eventbridge.py,sha256=abHxh0Iob6YrumdzmFugpRGWFqE0uVRVt89gajdq5q4,6062
88
+ src/snapshot/resource_collectors/glue.py,sha256=InEzfjcTDfVeKlM_XATEHKuOimle0QvaNBkbAYmPDto,7779
89
+ src/snapshot/resource_collectors/iam.py,sha256=N5QQO7E5opV-3CiOuoW_W0x-m_2alOjYs0-Q_loS-rQ,6732
90
+ src/snapshot/resource_collectors/kms.py,sha256=ioJUO2C7XawrGGnvpNA1pVT0GdHDI4pmbeqpACgf7Dc,4524
91
+ src/snapshot/resource_collectors/lambda_func.py,sha256=bjlWj_orHlU7vVT91c9ZcEAsXSPB7f4jgUWAMfa3C1w,5289
92
+ src/snapshot/resource_collectors/rds.py,sha256=Q4kdYZ4eDyLwAVTTM49PWh8Gg1NII-NBiY4_h5YafKw,4127
93
+ src/snapshot/resource_collectors/route53.py,sha256=oCFoEba-f80cf6e4R69Ovzp0eDgAZl_nNx4AkZ1L7zk,3311
94
+ src/snapshot/resource_collectors/s3.py,sha256=de90KYNHZ3b9UZ0csJlrw-Z5p1VgtU4sHyF0-5eft34,3749
95
+ src/snapshot/resource_collectors/secretsmanager.py,sha256=0daVuZE_VEk185boKM09Pc0A7E4b83jRztWYNMQm6bM,2673
96
+ src/snapshot/resource_collectors/sns.py,sha256=rsRyA95iBkildU2ytNeKihxOzwnwpUGkgZON2MOLTrY,2539
97
+ src/snapshot/resource_collectors/sqs.py,sha256=BK4LZJWjP7y2sItVEnn1-OHmDyNlhKlp--Bs2YIw7Mk,3112
98
+ src/snapshot/resource_collectors/ssm.py,sha256=EhyeGfK_17cqhDGuEM-KBg6TpAYj4kSNUvuNnfpeWes,6258
99
+ src/snapshot/resource_collectors/stepfunctions.py,sha256=I8TYniEzSX2jKZbSX6WI02eet5uP5ekn63uKnMaStEc,2950
100
+ src/snapshot/resource_collectors/vpcendpoints.py,sha256=tclcLPRxFmE5vwQQPwFQv2nbOc-4qVFnUaSJ4oDMU7w,2994
101
+ src/snapshot/resource_collectors/waf.py,sha256=HUNshQ_WHbIK3nAyNwhb21uHkMC7ywSOke28b-5ECRg,6461
102
+ src/storage/__init__.py,sha256=4LrT-bm45zLK6VUyKsx3jyK_L270A48t-w2-0ceb9PM,554
103
+ src/storage/audit_store.py,sha256=zO7L9o-8N31PsiLJ72wvmodoDrFtFeya05Ebfes8a5Y,14123
104
+ src/storage/database.py,sha256=j-IJ4LiNs7PgXH0L3FtMlmbId1TaGjNCcYjgn3dt7sQ,9465
105
+ src/storage/group_store.py,sha256=RLQK1dBkSbXiFtEw9twpoUFgnWiJWo6MyIMhVQkYoU8,25828
106
+ src/storage/inventory_store.py,sha256=hRxdL2oqDTvtIuyNiR9IoBFjH1jOe3DV43C8Ybt-aTU,10601
107
+ src/storage/resource_store.py,sha256=mfKiVQgok2z_PWi7cJx2VD_aMxL6ioI7TaPpEV5hS40,13220
108
+ src/storage/schema.py,sha256=JvHl5GrSPNyFntH7KDVMVG-_rebo3uxCtVoOUwxFKCc,12275
109
+ src/storage/snapshot_store.py,sha256=6BzGjsIljEetGQ88qXoGP5tsFxPNitT5ZVW2oRoCV_I,12589
110
+ src/utils/__init__.py,sha256=1qjjL3wxB7ye6s3AT4h5hQ9Xgi7y0WllUMmTpiZWC54,284
111
+ src/utils/export.py,sha256=lBUxLGkvtdzTFq2VKRmHgf18ZROiorHGGHlbeG7ixxc,8929
112
+ src/utils/hash.py,sha256=w6jJqNR64IEcgMIrIY-M1QXuo_CkH0sbT8I6JcFQJqo,1747
113
+ src/utils/logging.py,sha256=D39u9xrDSr_HlqedKa2yz-vmbCKulNAkJNVfG571UXY,2558
114
+ src/utils/pagination.py,sha256=BoMk2lP65-tGP1U6aUAuJPU7M-JroSvyfpScLKcGYxg,1153
115
+ src/utils/paths.py,sha256=EgO41-XE1KOmF0drY2YlJkzNQIb3WPsrGtPvsc0hVqY,1607
116
+ src/utils/progress.py,sha256=H8_6AtVsw-_-P40E57ECofkFw0v1Lq6uEVSofuxCXxY,936
117
+ src/utils/unsupported_resources.py,sha256=wN2fkN4Vpq2X_CXhpN2K0ewojeghrY3H4ARAL6lvCk4,10349
118
+ src/web/__init__.py,sha256=JIdxc2oP_DBW6BK8MFeYMCGGI-DO1K0ybUkML36Dg1A,100
119
+ src/web/app.py,sha256=G-cVVCakvBI3ErsHfE_RYznrjm6dnOeTbd0x6glypT4,2819
120
+ src/web/dependencies.py,sha256=Fp2J05-9rFYshs-fN_mlTPFPqpOsp5V3ilI5ReqwW6c,1736
121
+ src/web/routes/__init__.py,sha256=sFFDPD60smOOMalYMdiSFy0cmTM8co00A3ZZiP-915Q,26
122
+ src/web/routes/pages.py,sha256=TZjTMgQw88cpakJsYf4D3HdCTC5PgdoWXLH-zXg6oCs,5717
123
+ src/web/routes/api/__init__.py,sha256=q1ysdpJ1-3-Ux5sM3eH9nJCXya5AjeB077KnClVj1CI,712
124
+ src/web/routes/api/charts.py,sha256=V-2MtmsihptC9eikpw_u2VbJIyhMl-stUEO6QT27mSA,4136
125
+ src/web/routes/api/cleanup.py,sha256=27HOlGZJa4lh5cbuBWuVbtUgji7YVka-ojjswG-vhz8,6695
126
+ src/web/routes/api/filters.py,sha256=ILQmkxtpQjRh1XsRSmzet62Mfg-uVfl6UfLCDKzEqhM,7708
127
+ src/web/routes/api/groups.py,sha256=5ipRMBU8xpQHYtu29aJwfOmHYUMhu3kZWNxWVIRrQvg,8890
128
+ src/web/routes/api/inventories.py,sha256=dN2WSLlQB2HrDwOM9XdpM3dpoC2zDDE1V8O-Anculv4,2541
129
+ src/web/routes/api/queries.py,sha256=vETfCAaLk_HX9IQNbmKpc5XD4-cbs3UYrQA_uGjzkYw,5444
130
+ src/web/routes/api/resources.py,sha256=hJrpwXfp_nIPdmXYWN4NdPGFbiPcilodOW28wybKkBA,13691
131
+ src/web/routes/api/snapshots.py,sha256=rZHifGAB8abop1iungV8ubYE7bwMf5u55zyypbHy-uo,9860
132
+ src/web/routes/api/views.py,sha256=MSFr6woupQA3-ftwv0zhwNadlYlQAsBzTjfb3o-KwGg,7843
133
+ src/web/services/__init__.py,sha256=CdQNRtr3v5VA5wpZ2d4SqhxwtfaDacxs29IYrVlaCFg,28
134
+ src/web/templates/base.html,sha256=qt_q2mstFwLHkESksgpv6vKLBx1RV0uARQ1eGfZP52w,34295
135
+ src/web/templates/components/navbar.html,sha256=GX-rtm2vDSAcvY-lGaXvemTT04m9X5OIm9W60STl4Do,1997
136
+ src/web/templates/components/sidebar.html,sha256=TCclf5c3ss0f_D9P4H7R_uJLoqUxkUzTInCJZQ1f5No,9131
137
+ src/web/templates/pages/audit_logs.html,sha256=0shhlDlQ0Ghlxqu7wlAbSvEwv15G1V3gSratDVu1_nY,4930
138
+ src/web/templates/pages/cleanup.html,sha256=SzJPTY10ax_9T1XEM0juFLf1b5dyHcKHPQTIAUn-0cg,16204
139
+ src/web/templates/pages/dashboard.html,sha256=t6FKnpdkk6Um4JrtE5IJKF81KRMifVttCp09HjddXGs,10581
140
+ src/web/templates/pages/diff.html,sha256=UeRqKd6Op2XXNkNg916km7KICMPngh8FVxiaSQuxoO8,8489
141
+ src/web/templates/pages/error.html,sha256=rCnXvdqhrXQX8RungpL35q6iAU77ntQTnC-B52zYkdo,1715
142
+ src/web/templates/pages/groups.html,sha256=N2Bj44Bx5hTiXap9b_dIPjan_CS_9pAqJeJYAs5o-z0,43176
143
+ src/web/templates/pages/queries.html,sha256=sf167CjkCQmx0jZQsEorgSO2N3zVyISdEIpxkhZVr7E,12443
144
+ src/web/templates/pages/resources.html,sha256=eEjScuWjrEgHwZiol0_syofU8YkvIYzNhwyLyfm_UPs,134092
145
+ src/web/templates/pages/snapshot_detail.html,sha256=hHoM_smOhVnDhsqHRrjv_Bk3V2WsUcsjOhFEy6qqDDs,12457
146
+ src/web/templates/pages/snapshots.html,sha256=3b47IQgkN4mxJpqjUaJ_lPqYUqM2Icz44Ad8CesZpvM,22536
147
+ aws_inventory_manager-0.17.12.dist-info/LICENSE,sha256=-lY65BqqcGV9QVjIoTpYEB0Jaddm9j-cS5ICDRBRQo0,1071
148
+ aws_inventory_manager-0.17.12.dist-info/METADATA,sha256=limeZ6FFghh_zDijM_YPsGEj2cA0ph9jlVfA8pvtCQg,44693
149
+ aws_inventory_manager-0.17.12.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
150
+ aws_inventory_manager-0.17.12.dist-info/entry_points.txt,sha256=Ktdhto-PER5BtwWKYBtU_-FS3ngiGtAGGeoLzRW2qUw,44
151
+ aws_inventory_manager-0.17.12.dist-info/top_level.txt,sha256=74rtVfumQlgAPzR5_2CgYN24MB0XARCg0t-gzk6gTrM,4
152
+ aws_inventory_manager-0.17.12.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (76.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ awsinv = src.cli:cli_main
src/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ """AWS Baseline Snapshot & Delta Tracking tool."""
2
+
3
+ __version__ = "0.13.1"
src/aws/__init__.py ADDED
@@ -0,0 +1,11 @@
1
+ """AWS client utilities and wrappers."""
2
+
3
+ from .client import create_boto_client
4
+ from .credentials import validate_credentials
5
+ from .rate_limiter import RateLimiter
6
+
7
+ __all__ = [
8
+ "create_boto_client",
9
+ "validate_credentials",
10
+ "RateLimiter",
11
+ ]
src/aws/client.py ADDED
@@ -0,0 +1,128 @@
1
+ """Boto3 client wrapper with retry configuration and error handling."""
2
+
3
+ import logging
4
+ from typing import Any, List, Optional
5
+
6
+ import boto3
7
+ from botocore.config import Config
8
+ from botocore.exceptions import ClientError, NoCredentialsError
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ # Aggressive retry configuration for batch operations
14
+ DEFAULT_RETRY_CONFIG = Config(
15
+ retries={"max_attempts": 10, "mode": "adaptive"}, # Adaptive retry mode (boto3 1.16+)
16
+ max_pool_connections=50,
17
+ connect_timeout=60,
18
+ read_timeout=60,
19
+ )
20
+
21
+
22
+ def create_boto_client(
23
+ service_name: str,
24
+ region_name: str = "us-east-1",
25
+ profile_name: Optional[str] = None,
26
+ retry_config: Optional[Config] = None,
27
+ ) -> Any:
28
+ """Create boto3 client with retry configuration and error handling.
29
+
30
+ Args:
31
+ service_name: AWS service name (e.g., 'ec2', 'iam', 'lambda')
32
+ region_name: AWS region (default: 'us-east-1')
33
+ profile_name: AWS profile name from ~/.aws/config (optional)
34
+ retry_config: Custom botocore Config object (optional)
35
+
36
+ Returns:
37
+ Configured boto3 client
38
+
39
+ Raises:
40
+ NoCredentialsError: If AWS credentials are not found
41
+ ClientError: If client creation fails
42
+ """
43
+ if retry_config is None:
44
+ retry_config = DEFAULT_RETRY_CONFIG
45
+
46
+ try:
47
+ # Create session (with or without profile)
48
+ if profile_name:
49
+ session = boto3.Session(profile_name=profile_name)
50
+ client = session.client(service_name, region_name=region_name, config=retry_config)
51
+ else:
52
+ client = boto3.client(service_name, region_name=region_name, config=retry_config)
53
+
54
+ logger.debug(f"Created {service_name} client for region {region_name}")
55
+ return client
56
+
57
+ except NoCredentialsError:
58
+ logger.error("AWS credentials not found")
59
+ raise
60
+ except ClientError as e:
61
+ logger.error(f"Failed to create {service_name} client: {e}")
62
+ raise
63
+ except Exception as e:
64
+ logger.error(f"Unexpected error creating {service_name} client: {e}")
65
+ raise
66
+
67
+
68
+ def get_enabled_regions(profile_name: Optional[str] = None) -> List[str]: # type: ignore
69
+ """Get list of enabled AWS regions for the account.
70
+
71
+ Args:
72
+ profile_name: AWS profile name (optional)
73
+
74
+ Returns:
75
+ List of enabled region names
76
+ """
77
+ try:
78
+ ec2_client = create_boto_client("ec2", region_name="us-east-1", profile_name=profile_name)
79
+ response = ec2_client.describe_regions(AllRegions=False) # Only enabled regions
80
+ regions = [region["RegionName"] for region in response["Regions"]]
81
+ logger.info(f"Found {len(regions)} enabled regions")
82
+ return regions
83
+ except Exception as e:
84
+ logger.warning(f"Could not retrieve enabled regions: {e}")
85
+ # Return default set of common regions
86
+ return [
87
+ "us-east-1",
88
+ "us-east-2",
89
+ "us-west-1",
90
+ "us-west-2",
91
+ "eu-west-1",
92
+ "eu-central-1",
93
+ "ap-southeast-1",
94
+ "ap-northeast-1",
95
+ ]
96
+
97
+
98
+ def check_client_connection(client: Any) -> bool:
99
+ """Test if a boto3 client can connect to AWS.
100
+
101
+ Args:
102
+ client: Boto3 client instance
103
+
104
+ Returns:
105
+ True if connection successful, False otherwise
106
+ """
107
+ try:
108
+ # Different services have different test methods
109
+ service_name = client._service_model.service_name
110
+
111
+ if service_name == "sts":
112
+ client.get_caller_identity()
113
+ elif service_name == "ec2":
114
+ client.describe_regions(MaxResults=1)
115
+ elif service_name == "iam":
116
+ client.list_users(MaxItems=1)
117
+ elif service_name == "lambda":
118
+ client.list_functions(MaxItems=1)
119
+ elif service_name == "s3":
120
+ client.list_buckets()
121
+ else:
122
+ # Generic test - just try to get service metadata
123
+ client._make_api_call("ListObjects", {})
124
+
125
+ return True
126
+ except Exception as e:
127
+ logger.debug(f"Client connection test failed: {e}")
128
+ return False
src/aws/credentials.py ADDED
@@ -0,0 +1,191 @@
1
+ """AWS credential validation and permission checking."""
2
+
3
+ import logging
4
+ from typing import Any, Dict, List, Optional
5
+
6
+ import boto3
7
+ from botocore.exceptions import ClientError, NoCredentialsError, PartialCredentialsError
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ class CredentialValidationError(Exception):
13
+ """Raised when AWS credentials are invalid or missing."""
14
+
15
+ pass
16
+
17
+
18
+ def validate_credentials(profile_name: Optional[str] = None) -> Dict[str, Any]:
19
+ """Validate AWS credentials and return caller identity information.
20
+
21
+ Args:
22
+ profile_name: AWS profile name from ~/.aws/config (optional)
23
+
24
+ Returns:
25
+ Dictionary with account ID, user ID, and ARN
26
+
27
+ Raises:
28
+ CredentialValidationError: If credentials are invalid or missing
29
+ """
30
+ try:
31
+ if profile_name:
32
+ session = boto3.Session(profile_name=profile_name)
33
+ sts_client = session.client("sts")
34
+ else:
35
+ sts_client = boto3.client("sts")
36
+
37
+ # Get caller identity to validate credentials
38
+ identity = sts_client.get_caller_identity()
39
+
40
+ logger.debug(f"Validated credentials for account {identity['Account']}")
41
+
42
+ return {
43
+ "account_id": identity["Account"],
44
+ "user_id": identity["UserId"],
45
+ "arn": identity["Arn"],
46
+ }
47
+
48
+ except NoCredentialsError:
49
+ error_msg = (
50
+ "AWS credentials not found. Please configure credentials using one of these methods:\n"
51
+ " 1. Run: aws configure\n"
52
+ " 2. Set environment variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY\n"
53
+ " 3. Use --profile option with a configured profile\n\n"
54
+ "For more info: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html"
55
+ )
56
+ logger.error("No AWS credentials found")
57
+ raise CredentialValidationError(error_msg)
58
+
59
+ except PartialCredentialsError as e:
60
+ error_msg = f"Incomplete AWS credentials: {e}"
61
+ logger.error(error_msg)
62
+ raise CredentialValidationError(error_msg)
63
+
64
+ except ClientError as e:
65
+ error_code = e.response.get("Error", {}).get("Code", "Unknown")
66
+ if error_code == "InvalidClientTokenId":
67
+ error_msg = "AWS credentials are invalid. Please check your access key ID."
68
+ elif error_code == "SignatureDoesNotMatch":
69
+ error_msg = "AWS credentials signature mismatch. Please check your secret access key."
70
+ elif error_code == "ExpiredToken":
71
+ error_msg = "AWS credentials have expired. Please refresh your temporary credentials."
72
+ else:
73
+ error_msg = f"AWS credential validation failed: {e}"
74
+
75
+ logger.error(error_msg)
76
+ raise CredentialValidationError(error_msg)
77
+
78
+ except Exception as e:
79
+ error_msg = f"Unexpected error validating credentials: {e}"
80
+ logger.error(error_msg)
81
+ raise CredentialValidationError(error_msg)
82
+
83
+
84
+ def check_required_permissions(
85
+ profile_name: Optional[str] = None, required_actions: Optional[List[str]] = None
86
+ ) -> Dict[str, bool]:
87
+ """Check if credentials have required IAM permissions.
88
+
89
+ Note: This is a best-effort check using IAM policy simulation.
90
+ Some permissions may not be accurately detected.
91
+
92
+ Args:
93
+ profile_name: AWS profile name (optional)
94
+ required_actions: List of IAM actions to check (e.g., ['ec2:DescribeInstances'])
95
+
96
+ Returns:
97
+ Dictionary mapping action names to permission status (True/False)
98
+ """
99
+ if required_actions is None:
100
+ # Default minimum required permissions for snapshot operations
101
+ required_actions = [
102
+ "ec2:DescribeInstances",
103
+ "ec2:DescribeRegions",
104
+ "iam:ListRoles",
105
+ "lambda:ListFunctions",
106
+ "s3:ListAllMyBuckets",
107
+ ]
108
+
109
+ try:
110
+ # Get caller identity first
111
+ identity = validate_credentials(profile_name)
112
+
113
+ if profile_name:
114
+ session = boto3.Session(profile_name=profile_name)
115
+ iam_client = session.client("iam")
116
+ else:
117
+ iam_client = boto3.client("iam")
118
+
119
+ results = {}
120
+
121
+ # Try to simulate policy for each action
122
+ for action in required_actions:
123
+ try:
124
+ response = iam_client.simulate_principal_policy(
125
+ PolicySourceArn=identity["arn"],
126
+ ActionNames=[action],
127
+ )
128
+
129
+ # Check if action is allowed
130
+ eval_results = response.get("EvaluationResults", [])
131
+ if eval_results:
132
+ decision = eval_results[0].get("EvalDecision", "deny")
133
+ results[action] = decision.lower() == "allowed"
134
+ else:
135
+ results[action] = False
136
+
137
+ except ClientError as e:
138
+ # If simulation fails (e.g., lack of iam:SimulatePrincipalPolicy permission),
139
+ # we can't determine the permission status
140
+ logger.debug(f"Could not check permission for {action}: {e}")
141
+ results[action] = None # Unknown
142
+
143
+ return results
144
+
145
+ except Exception as e:
146
+ logger.warning(f"Permission check failed: {e}")
147
+ return {action: None for action in required_actions} # type: ignore
148
+
149
+
150
+ def get_account_id(profile_name: Optional[str] = None) -> str:
151
+ """Get AWS account ID for the current credentials.
152
+
153
+ Args:
154
+ profile_name: AWS profile name (optional)
155
+
156
+ Returns:
157
+ 12-digit AWS account ID
158
+
159
+ Raises:
160
+ CredentialValidationError: If credentials are invalid
161
+ """
162
+ identity = validate_credentials(profile_name)
163
+ return identity["account_id"]
164
+
165
+
166
+ def get_credential_summary(profile_name: Optional[str] = None) -> str:
167
+ """Get a human-readable summary of current AWS credentials.
168
+
169
+ Args:
170
+ profile_name: AWS profile name (optional)
171
+
172
+ Returns:
173
+ Formatted string with credential information
174
+ """
175
+ try:
176
+ identity = validate_credentials(profile_name)
177
+
178
+ summary = f"""
179
+ AWS Credentials Valid
180
+ Account ID: {identity['account_id']}
181
+ User/Role: {identity['arn'].split('/')[-1]}
182
+ ARN: {identity['arn']}
183
+ """
184
+
185
+ if profile_name:
186
+ summary += f"Profile: {profile_name}\n"
187
+
188
+ return summary.strip()
189
+
190
+ except CredentialValidationError as e:
191
+ return f"Credential Validation Failed:\n{e}"