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.
- aws_inventory_manager-0.17.12.dist-info/LICENSE +21 -0
- aws_inventory_manager-0.17.12.dist-info/METADATA +1292 -0
- aws_inventory_manager-0.17.12.dist-info/RECORD +152 -0
- aws_inventory_manager-0.17.12.dist-info/WHEEL +5 -0
- aws_inventory_manager-0.17.12.dist-info/entry_points.txt +2 -0
- aws_inventory_manager-0.17.12.dist-info/top_level.txt +1 -0
- src/__init__.py +3 -0
- src/aws/__init__.py +11 -0
- src/aws/client.py +128 -0
- src/aws/credentials.py +191 -0
- src/aws/rate_limiter.py +177 -0
- src/cli/__init__.py +12 -0
- src/cli/config.py +130 -0
- src/cli/main.py +4046 -0
- src/cloudtrail/__init__.py +5 -0
- src/cloudtrail/query.py +642 -0
- src/config_service/__init__.py +21 -0
- src/config_service/collector.py +346 -0
- src/config_service/detector.py +256 -0
- src/config_service/resource_type_mapping.py +328 -0
- src/cost/__init__.py +5 -0
- src/cost/analyzer.py +226 -0
- src/cost/explorer.py +209 -0
- src/cost/reporter.py +237 -0
- src/delta/__init__.py +5 -0
- src/delta/calculator.py +206 -0
- src/delta/differ.py +185 -0
- src/delta/formatters.py +272 -0
- src/delta/models.py +154 -0
- src/delta/reporter.py +234 -0
- src/matching/__init__.py +6 -0
- src/matching/config.py +52 -0
- src/matching/normalizer.py +450 -0
- src/matching/prompts.py +33 -0
- src/models/__init__.py +21 -0
- src/models/config_diff.py +135 -0
- src/models/cost_report.py +87 -0
- src/models/deletion_operation.py +104 -0
- src/models/deletion_record.py +97 -0
- src/models/delta_report.py +122 -0
- src/models/efs_resource.py +80 -0
- src/models/elasticache_resource.py +90 -0
- src/models/group.py +318 -0
- src/models/inventory.py +133 -0
- src/models/protection_rule.py +123 -0
- src/models/report.py +288 -0
- src/models/resource.py +111 -0
- src/models/security_finding.py +102 -0
- src/models/snapshot.py +122 -0
- src/restore/__init__.py +20 -0
- src/restore/audit.py +175 -0
- src/restore/cleaner.py +461 -0
- src/restore/config.py +209 -0
- src/restore/deleter.py +976 -0
- src/restore/dependency.py +254 -0
- src/restore/safety.py +115 -0
- src/security/__init__.py +0 -0
- src/security/checks/__init__.py +0 -0
- src/security/checks/base.py +56 -0
- src/security/checks/ec2_checks.py +88 -0
- src/security/checks/elasticache_checks.py +149 -0
- src/security/checks/iam_checks.py +102 -0
- src/security/checks/rds_checks.py +140 -0
- src/security/checks/s3_checks.py +95 -0
- src/security/checks/secrets_checks.py +96 -0
- src/security/checks/sg_checks.py +142 -0
- src/security/cis_mapper.py +97 -0
- src/security/models.py +53 -0
- src/security/reporter.py +174 -0
- src/security/scanner.py +87 -0
- src/snapshot/__init__.py +6 -0
- src/snapshot/capturer.py +453 -0
- src/snapshot/filter.py +259 -0
- src/snapshot/inventory_storage.py +236 -0
- src/snapshot/report_formatter.py +250 -0
- src/snapshot/reporter.py +189 -0
- src/snapshot/resource_collectors/__init__.py +5 -0
- src/snapshot/resource_collectors/apigateway.py +140 -0
- src/snapshot/resource_collectors/backup.py +136 -0
- src/snapshot/resource_collectors/base.py +81 -0
- src/snapshot/resource_collectors/cloudformation.py +55 -0
- src/snapshot/resource_collectors/cloudwatch.py +109 -0
- src/snapshot/resource_collectors/codebuild.py +69 -0
- src/snapshot/resource_collectors/codepipeline.py +82 -0
- src/snapshot/resource_collectors/dynamodb.py +65 -0
- src/snapshot/resource_collectors/ec2.py +240 -0
- src/snapshot/resource_collectors/ecs.py +215 -0
- src/snapshot/resource_collectors/efs_collector.py +102 -0
- src/snapshot/resource_collectors/eks.py +200 -0
- src/snapshot/resource_collectors/elasticache_collector.py +79 -0
- src/snapshot/resource_collectors/elb.py +126 -0
- src/snapshot/resource_collectors/eventbridge.py +156 -0
- src/snapshot/resource_collectors/glue.py +199 -0
- src/snapshot/resource_collectors/iam.py +188 -0
- src/snapshot/resource_collectors/kms.py +111 -0
- src/snapshot/resource_collectors/lambda_func.py +139 -0
- src/snapshot/resource_collectors/rds.py +109 -0
- src/snapshot/resource_collectors/route53.py +86 -0
- src/snapshot/resource_collectors/s3.py +105 -0
- src/snapshot/resource_collectors/secretsmanager.py +70 -0
- src/snapshot/resource_collectors/sns.py +68 -0
- src/snapshot/resource_collectors/sqs.py +82 -0
- src/snapshot/resource_collectors/ssm.py +160 -0
- src/snapshot/resource_collectors/stepfunctions.py +74 -0
- src/snapshot/resource_collectors/vpcendpoints.py +79 -0
- src/snapshot/resource_collectors/waf.py +159 -0
- src/snapshot/storage.py +351 -0
- src/storage/__init__.py +21 -0
- src/storage/audit_store.py +419 -0
- src/storage/database.py +294 -0
- src/storage/group_store.py +763 -0
- src/storage/inventory_store.py +320 -0
- src/storage/resource_store.py +416 -0
- src/storage/schema.py +339 -0
- src/storage/snapshot_store.py +363 -0
- src/utils/__init__.py +12 -0
- src/utils/export.py +305 -0
- src/utils/hash.py +60 -0
- src/utils/logging.py +63 -0
- src/utils/pagination.py +41 -0
- src/utils/paths.py +51 -0
- src/utils/progress.py +41 -0
- src/utils/unsupported_resources.py +306 -0
- src/web/__init__.py +5 -0
- src/web/app.py +97 -0
- src/web/dependencies.py +69 -0
- src/web/routes/__init__.py +1 -0
- src/web/routes/api/__init__.py +18 -0
- src/web/routes/api/charts.py +156 -0
- src/web/routes/api/cleanup.py +186 -0
- src/web/routes/api/filters.py +253 -0
- src/web/routes/api/groups.py +305 -0
- src/web/routes/api/inventories.py +80 -0
- src/web/routes/api/queries.py +202 -0
- src/web/routes/api/resources.py +393 -0
- src/web/routes/api/snapshots.py +314 -0
- src/web/routes/api/views.py +260 -0
- src/web/routes/pages.py +198 -0
- src/web/services/__init__.py +1 -0
- src/web/templates/base.html +955 -0
- src/web/templates/components/navbar.html +31 -0
- src/web/templates/components/sidebar.html +104 -0
- src/web/templates/pages/audit_logs.html +86 -0
- src/web/templates/pages/cleanup.html +279 -0
- src/web/templates/pages/dashboard.html +227 -0
- src/web/templates/pages/diff.html +175 -0
- src/web/templates/pages/error.html +30 -0
- src/web/templates/pages/groups.html +721 -0
- src/web/templates/pages/queries.html +246 -0
- src/web/templates/pages/resources.html +2429 -0
- src/web/templates/pages/snapshot_detail.html +271 -0
- 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 @@
|
|
|
1
|
+
src
|
src/__init__.py
ADDED
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}"
|