cartography 0.93.0rc1__py3-none-any.whl → 0.94.0rc2__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 cartography might be problematic. Click here for more details.

@@ -3,6 +3,7 @@ from typing import Any
3
3
 
4
4
  import boto3
5
5
  import neo4j
6
+ from botocore.exceptions import ClientError
6
7
 
7
8
  from .util import get_botocore_config
8
9
  from cartography.client.core.tx import load
@@ -17,13 +18,30 @@ logger = logging.getLogger(__name__)
17
18
 
18
19
  @timeit
19
20
  @aws_handle_regions
20
- def get_launch_templates(boto3_session: boto3.session.Session, region: str) -> list[dict[str, Any]]:
21
+ def get_launch_templates(
22
+ boto3_session: boto3.session.Session,
23
+ region: str,
24
+ ) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
21
25
  client = boto3_session.client('ec2', region_name=region, config=get_botocore_config())
22
26
  paginator = client.get_paginator('describe_launch_templates')
23
27
  templates: list[dict[str, Any]] = []
28
+ template_versions: list[dict[str, Any]] = []
24
29
  for page in paginator.paginate():
25
- templates.extend(page['LaunchTemplates'])
26
- return templates
30
+ paginated_templates = page['LaunchTemplates']
31
+ for template in paginated_templates:
32
+ template_id = template['LaunchTemplateId']
33
+ try:
34
+ versions = get_launch_template_versions_by_template(boto3_session, template_id, region)
35
+ except ClientError as e:
36
+ logger.warning(
37
+ f"Failed to get launch template versions for {template_id}: {e}",
38
+ exc_info=True,
39
+ )
40
+ versions = []
41
+ # Using a key not defined in latest boto3 documentation
42
+ template_versions.extend(versions)
43
+ templates.extend(paginated_templates)
44
+ return templates, template_versions
27
45
 
28
46
 
29
47
  def transform_launch_templates(templates: list[dict[str, Any]]) -> list[dict[str, Any]]:
@@ -55,17 +73,16 @@ def load_launch_templates(
55
73
 
56
74
  @timeit
57
75
  @aws_handle_regions
58
- def get_launch_template_versions(
76
+ def get_launch_template_versions_by_template(
59
77
  boto3_session: boto3.session.Session,
60
- templates: list[dict[str, Any]],
78
+ template: str,
61
79
  region: str,
62
80
  ) -> list[dict[str, Any]]:
63
81
  client = boto3_session.client('ec2', region_name=region, config=get_botocore_config())
64
82
  v_paginator = client.get_paginator('describe_launch_template_versions')
65
83
  template_versions = []
66
- for template in templates:
67
- for versions in v_paginator.paginate(LaunchTemplateId=template['LaunchTemplateId']):
68
- template_versions.extend(versions['LaunchTemplateVersions'])
84
+ for versions in v_paginator.paginate(LaunchTemplateId=template):
85
+ template_versions.extend(versions['LaunchTemplateVersions'])
69
86
  return template_versions
70
87
 
71
88
 
@@ -136,11 +153,9 @@ def sync_ec2_launch_templates(
136
153
  ) -> None:
137
154
  for region in regions:
138
155
  logger.info(f"Syncing launch templates for region '{region}' in account '{current_aws_account_id}'.")
139
- templates = get_launch_templates(boto3_session, region)
156
+ templates, versions = get_launch_templates(boto3_session, region)
140
157
  templates = transform_launch_templates(templates)
141
158
  load_launch_templates(neo4j_session, templates, region, current_aws_account_id, update_tag)
142
-
143
- versions = get_launch_template_versions(boto3_session, templates, region)
144
159
  versions = transform_launch_template_versions(versions)
145
160
  load_launch_template_versions(neo4j_session, versions, region, current_aws_account_id, update_tag)
146
161
 
@@ -18,6 +18,15 @@ from cartography.util import timeit
18
18
 
19
19
  logger = logging.getLogger(__name__)
20
20
 
21
+ # As of 7/22/24, Inspector is only available in the below regions. We will need to update this hardcoded list here over
22
+ # time. :\ https://docs.aws.amazon.com/general/latest/gr/inspector2.html
23
+ AWS_INSPECTOR_REGIONS = {
24
+ "us-east-2", "us-east-1", "us-west-1", "us-west-2", "af-south-1", "ap-east-1", "ap-southeast-3", "ap-south-1",
25
+ "ap-northeast-3", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "ap-northeast-1", "ca-central-1",
26
+ "eu-central-1", "eu-west-1", "eu-west-2", "eu-south-1", "eu-west-3", "eu-north-1", "eu-central-2", "me-south-1",
27
+ "sa-east-1",
28
+ }
29
+
21
30
 
22
31
  @timeit
23
32
  @aws_handle_regions
@@ -206,7 +215,9 @@ def sync(
206
215
  update_tag: int,
207
216
  common_job_parameters: Dict[str, Any],
208
217
  ) -> None:
209
- for region in regions:
218
+ inspector_regions = [region for region in regions if region in AWS_INSPECTOR_REGIONS]
219
+
220
+ for region in inspector_regions:
210
221
  logger.info(f"Syncing AWS Inspector findings for account {current_aws_account_id} and region {region}")
211
222
  findings = get_inspector_findings(boto3_session, region, current_aws_account_id)
212
223
  finding_data, package_data = transform_inspector_findings(findings)
@@ -1,4 +1,6 @@
1
1
  import logging
2
+ from collections import namedtuple
3
+ from time import sleep
2
4
  from typing import Any
3
5
  from typing import Dict
4
6
  from typing import List
@@ -15,6 +17,8 @@ from cartography.util import timeit
15
17
 
16
18
  logger = logging.getLogger(__name__)
17
19
 
20
+ RepoPermission = namedtuple('RepoPermission', ['repo_url', 'permission'])
21
+
18
22
 
19
23
  @timeit
20
24
  def get_teams(org: str, api_url: str, token: str) -> Tuple[PaginatedGraphqlData, Dict[str, Any]]:
@@ -45,26 +49,53 @@ def get_teams(org: str, api_url: str, token: str) -> Tuple[PaginatedGraphqlData,
45
49
 
46
50
  @timeit
47
51
  def _get_team_repos_for_multiple_teams(
48
- team_raw_data: List[Dict[str, Any]],
52
+ team_raw_data: list[dict[str, Any]],
49
53
  org: str,
50
54
  api_url: str,
51
55
  token: str,
52
- ) -> Dict[str, Any]:
53
- result = {}
56
+ ) -> dict[str, list[RepoPermission]]:
57
+ result: dict[str, list[RepoPermission]] = {}
54
58
  for team in team_raw_data:
55
59
  team_name = team['slug']
56
60
  repo_count = team['repositories']['totalCount']
57
61
 
58
- team_repos = _get_team_repos(org, api_url, token, team_name) if repo_count > 0 else None
62
+ if repo_count == 0:
63
+ # This team has access to no repos so let's move on
64
+ result[team_name] = []
65
+ continue
59
66
 
60
67
  repo_urls = []
61
68
  repo_permissions = []
62
- if team_repos:
63
- repo_urls = [t['url'] for t in team_repos.nodes] if team_repos.nodes else []
64
- repo_permissions = [t['permission'] for t in team_repos.edges] if team_repos.edges else []
69
+
70
+ max_tries = 5
71
+
72
+ for current_try in range(1, max_tries + 1):
73
+ team_repos = _get_team_repos(org, api_url, token, team_name)
74
+
75
+ try:
76
+ # The `or []` is because `.nodes` can be None. See:
77
+ # https://docs.github.com/en/graphql/reference/objects#teamrepositoryconnection
78
+ for repo in team_repos.nodes or []:
79
+ repo_urls.append(repo['url'])
80
+
81
+ # The `or []` is because `.edges` can be None.
82
+ for edge in team_repos.edges or []:
83
+ repo_permissions.append(edge['permission'])
84
+ # We're done! Break out of the retry loop.
85
+ break
86
+
87
+ except TypeError:
88
+ # Handles issue #1334
89
+ logger.warning(
90
+ f"GitHub returned None when trying to find repo or permission data for team {team_name}.",
91
+ exc_info=True,
92
+ )
93
+ if current_try == max_tries:
94
+ raise RuntimeError(f"GitHub returned a None repo url for team {team_name}, retries exhausted.")
95
+ sleep(current_try ** 2)
65
96
 
66
97
  # Shape = [(repo_url, 'WRITE'), ...]]
67
- result[team_name] = list(zip(repo_urls, repo_permissions))
98
+ result[team_name] = [RepoPermission(url, perm) for url, perm in zip(repo_urls, repo_permissions)]
68
99
  return result
69
100
 
70
101
 
@@ -114,8 +145,8 @@ def _get_team_repos(org: str, api_url: str, token: str, team: str) -> PaginatedG
114
145
  def transform_teams(
115
146
  team_paginated_data: PaginatedGraphqlData,
116
147
  org_data: Dict[str, Any],
117
- team_repo_data: Dict[str, Any],
118
- ) -> List[Dict[str, Any]]:
148
+ team_repo_data: dict[str, list[RepoPermission]],
149
+ ) -> list[dict[str, Any]]:
119
150
  result = []
120
151
  for team in team_paginated_data.nodes:
121
152
  team_name = team['slug']
cartography/util.py CHANGED
@@ -225,7 +225,7 @@ If not, then the AWS datatype somehow does not have this key.''',
225
225
  return items
226
226
 
227
227
 
228
- AWSGetFunc = TypeVar('AWSGetFunc', bound=Callable[..., List])
228
+ AWSGetFunc = TypeVar('AWSGetFunc', bound=Callable[..., Iterable])
229
229
 
230
230
  # fix for AWS TooManyRequestsException
231
231
  # https://github.com/lyft/cartography/issues/297
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cartography
3
- Version: 0.93.0rc1
3
+ Version: 0.94.0rc2
4
4
  Summary: Explore assets and their relationships across your technical infrastructure.
5
5
  Home-page: https://www.github.com/lyft/cartography
6
6
  Maintainer: Lyft
@@ -5,7 +5,7 @@ cartography/config.py,sha256=rL1zgxZO47_R7S6E9e0CwxmhzRSN0X_q93NtcPR1G00,11368
5
5
  cartography/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  cartography/stats.py,sha256=dbybb9V2FuvSuHjjNwz6Vjwnd1hap2C7h960rLoKcl8,4406
7
7
  cartography/sync.py,sha256=a80r_IzrZcWGSmRDRrxkesNYPiOuLte5YHvDQT3L-Lw,9730
8
- cartography/util.py,sha256=F3FPMJl1KDW0x_5cvt2ZGI0Dv1LVrHU7Az4OleAANBI,14474
8
+ cartography/util.py,sha256=umfnjX8jVLu0rpYA75X-WvRpYzHQxns9qZiPwfyAlwQ,14478
9
9
  cartography/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  cartography/client/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  cartography/client/aws/iam.py,sha256=dYsGikc36DEsSeR2XVOVFFUDwuU9yWj_EVkpgVYCFgM,1293
@@ -153,7 +153,7 @@ cartography/intel/aws/elasticache.py,sha256=fCI47aDFmIDyE26GiReKYb6XIZUwrzcvsXBQ
153
153
  cartography/intel/aws/elasticsearch.py,sha256=ZL7MkXF_bXRSoXuDSI1dwGckRLG2zDB8LuAD07vSLnE,8374
154
154
  cartography/intel/aws/emr.py,sha256=xhWBVZngxJRFjMEDxwq3G6SgytRGLq0v2a_CeDvByR0,3372
155
155
  cartography/intel/aws/iam.py,sha256=eLw0NkBGKzCI_tQ3wmrx3aUibQerrsxKJd3d0RCKcKQ,32374
156
- cartography/intel/aws/inspector.py,sha256=6enCu2USefuGT3FqA0Vto6i-z4BrL2HC_clbiXSLIlo,8654
156
+ cartography/intel/aws/inspector.py,sha256=S22ZgRKEnmnBTJ-u0rodqRPB7_LkSIek47NeBxN4XJw,9336
157
157
  cartography/intel/aws/kms.py,sha256=bZUzMxAH_DsAcGTJBs08gg2tLKYu-QWjvMvV9C-6v50,11731
158
158
  cartography/intel/aws/lambda_function.py,sha256=KKTyn53xpaMI9WvIqxmsOASFwflHt-2_5ow-zUFc2wg,9890
159
159
  cartography/intel/aws/organizations.py,sha256=HaQZ3J5XF15BuykuDypqFORDYpnoHuRRr4DuceewH4s,4485
@@ -175,7 +175,7 @@ cartography/intel/aws/ec2/images.py,sha256=heElwHJGqVD3iUJjxwA_Sdc3CmE4HPs00CTMH
175
175
  cartography/intel/aws/ec2/instances.py,sha256=mnTjdBY-4D-TGhH29UrSaLUW0Uft0JApDIJkkLz4zPc,12170
176
176
  cartography/intel/aws/ec2/internet_gateways.py,sha256=dI-4-85_3DGGZZBcY_DN6XqESx9P26S6jKok314lcnQ,2883
177
177
  cartography/intel/aws/ec2/key_pairs.py,sha256=SvRgd56vE4eouvTSNoFK8PP8HYoECO91goxc36oq_FY,2508
178
- cartography/intel/aws/ec2/launch_templates.py,sha256=YhLh_O2cZbeoKXA6MXmwkxJJi0ubZb5FyouTYykuq1k,5372
178
+ cartography/intel/aws/ec2/launch_templates.py,sha256=aeqaL8On38ET8nM8bISsIXLy6PkZoV-tqSWG38YXgkI,6010
179
179
  cartography/intel/aws/ec2/load_balancer_v2s.py,sha256=95FfQQn740gexINIHDJizOM4OKzRtQT_y2XQMipQ5Dg,8661
180
180
  cartography/intel/aws/ec2/load_balancers.py,sha256=1GwErzGqi3BKCARqfGJcD_r_D84rFKVy5kNMas9jAok,6756
181
181
  cartography/intel/aws/ec2/network_interfaces.py,sha256=CzF8PooCYUQ2pk8DR8JDAhkWRUQSBj_27OsIfkL_-Cs,9199
@@ -230,7 +230,7 @@ cartography/intel/gcp/gke.py,sha256=qaTwsVaxkwNhW5_Mw4bedOk7fgJK8y0LwwcYlUABXDg,
230
230
  cartography/intel/gcp/storage.py,sha256=oO_ayEhkXlj2Gn7T5MU41ZXiqwRwe6Ud4wzqyRTsyf4,9075
231
231
  cartography/intel/github/__init__.py,sha256=y876JJGTDJZEOFCDiNCJfcLNxN24pVj4s2N0YmuuoaE,1914
232
232
  cartography/intel/github/repos.py,sha256=YPDdBMk6NkZjwPcqPW5LlCy_OS9tKcrZD6ygiUG93J0,21766
233
- cartography/intel/github/teams.py,sha256=mofyJeJVOD7Umh9Rq6QnAwom9bBHBx18kyvFMvQX5YE,5383
233
+ cartography/intel/github/teams.py,sha256=aXI-XbxlA1IDaAUX0XSdEt6pA2n4ew5j_doj1iNYCDM,6618
234
234
  cartography/intel/github/users.py,sha256=kQp0dxzP08DVrdvfVeCciQbrKPbbFvwbR_p_I_XGt7s,3826
235
235
  cartography/intel/github/util.py,sha256=K6hbxypy4luKhIE1Uh5VWZc9OyjMK2OuO00vBAQfloA,8049
236
236
  cartography/intel/gsuite/__init__.py,sha256=AGIUskGlLCVGHbnQicNpNWi9AvmV7_7hUKTt-hsB2J8,4306
@@ -332,10 +332,10 @@ cartography/models/semgrep/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
332
332
  cartography/models/semgrep/deployment.py,sha256=or5qZDuR51MXzINpH15jZrqmSUvXQevCNYWJ7D6v-JI,745
333
333
  cartography/models/semgrep/findings.py,sha256=xrn8sgXpNMrNJbKQagaAVxaCG9bVjTATSRR2XRBR4rg,5386
334
334
  cartography/models/semgrep/locations.py,sha256=kSk7Nn5Mn4Ob84MVZOo2GR0YFi-9Okq9pgA3FfC6_bk,3061
335
- cartography-0.93.0rc1.dist-info/LICENSE,sha256=489ZXeW9G90up6ep-D1n-lJgk9ciNT2yxXpFgRSidtk,11341
336
- cartography-0.93.0rc1.dist-info/METADATA,sha256=1r_kEpkQWTPR77ToFbTkU78iBSTCM9JuQdleKFo3dJE,1991
337
- cartography-0.93.0rc1.dist-info/NOTICE,sha256=YOGAsjFtbyKj5tslYIg6V5jEYRuEvnSsIuDOUKj0Qj4,97
338
- cartography-0.93.0rc1.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
339
- cartography-0.93.0rc1.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
340
- cartography-0.93.0rc1.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
341
- cartography-0.93.0rc1.dist-info/RECORD,,
335
+ cartography-0.94.0rc2.dist-info/LICENSE,sha256=489ZXeW9G90up6ep-D1n-lJgk9ciNT2yxXpFgRSidtk,11341
336
+ cartography-0.94.0rc2.dist-info/METADATA,sha256=UEwu0NxrNz1H3YQWCQT4grTn4p_yvqC1nFoou0HCvig,1991
337
+ cartography-0.94.0rc2.dist-info/NOTICE,sha256=YOGAsjFtbyKj5tslYIg6V5jEYRuEvnSsIuDOUKj0Qj4,97
338
+ cartography-0.94.0rc2.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
339
+ cartography-0.94.0rc2.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
340
+ cartography-0.94.0rc2.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
341
+ cartography-0.94.0rc2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.3.0)
2
+ Generator: setuptools (71.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5