cartography 0.99.0rc1__py3-none-any.whl → 0.100.0rc1__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.

cartography/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.99.0rc1'
16
- __version_tuple__ = version_tuple = (0, 99, 0)
15
+ __version__ = version = '0.100.0rc1'
16
+ __version_tuple__ = version_tuple = (0, 100, 0)
@@ -12,8 +12,13 @@ import neo4j
12
12
  from botocore.exceptions import ClientError
13
13
  from policyuniverse.policy import Policy
14
14
 
15
+ from cartography.client.core.tx import load
16
+ from cartography.graph.job import GraphJob
17
+ from cartography.models.aws.apigateway import APIGatewayRestAPISchema
18
+ from cartography.models.aws.apigatewaycertificate import APIGatewayClientCertificateSchema
19
+ from cartography.models.aws.apigatewayresource import APIGatewayResourceSchema
20
+ from cartography.models.aws.apigatewaystage import APIGatewayStageSchema
15
21
  from cartography.util import aws_handle_regions
16
- from cartography.util import run_cleanup_job
17
22
  from cartography.util import timeit
18
23
 
19
24
  logger = logging.getLogger(__name__)
@@ -107,222 +112,146 @@ def get_rest_api_policy(api: Dict, client: botocore.client.BaseClient) -> Any:
107
112
  return policy
108
113
 
109
114
 
110
- @timeit
111
- def load_apigateway_rest_apis(
112
- neo4j_session: neo4j.Session, rest_apis: List[Dict], region: str, current_aws_account_id: str,
113
- aws_update_tag: int,
114
- ) -> None:
115
- """
116
- Ingest the details of API Gateway REST APIs into neo4j.
115
+ def transform_apigateway_rest_apis(
116
+ rest_apis: List[Dict], resource_policies: List[Dict], region: str, current_aws_account_id: str, aws_update_tag: int,
117
+ ) -> List[Dict]:
117
118
  """
118
- ingest_rest_apis = """
119
- UNWIND $rest_apis_list AS r
120
- MERGE (rest_api:APIGatewayRestAPI{id:r.id})
121
- ON CREATE SET rest_api.firstseen = timestamp(),
122
- rest_api.createddate = r.createdDate
123
- SET rest_api.version = r.version,
124
- rest_api.minimumcompressionsize = r.minimumCompressionSize,
125
- rest_api.disableexecuteapiendpoint = r.disableExecuteApiEndpoint,
126
- rest_api.lastupdated = $aws_update_tag,
127
- rest_api.region = $Region
128
- WITH rest_api
129
- MATCH (aa:AWSAccount{id: $AWS_ACCOUNT_ID})
130
- MERGE (aa)-[r:RESOURCE]->(rest_api)
131
- ON CREATE SET r.firstseen = timestamp()
132
- SET r.lastupdated = $aws_update_tag
119
+ Transform API Gateway REST API data for ingestion, including policy analysis
133
120
  """
121
+ # Create a mapping of api_id to policy data for easier lookup
122
+ policy_map = {
123
+ policy['api_id']: policy
124
+ for policy in resource_policies
125
+ }
134
126
 
135
- # neo4j does not accept datetime objects and values. This loop is used to convert
136
- # these values to string.
127
+ transformed_apis = []
137
128
  for api in rest_apis:
138
- api['createdDate'] = str(api['createdDate']) if 'createdDate' in api else None
139
-
140
- neo4j_session.run(
141
- ingest_rest_apis,
142
- rest_apis_list=rest_apis,
143
- aws_update_tag=aws_update_tag,
144
- Region=region,
145
- AWS_ACCOUNT_ID=current_aws_account_id,
146
- )
129
+ policy_data = policy_map.get(api['id'], {})
130
+ transformed_api = {
131
+ 'id': api['id'],
132
+ 'createdDate': str(api['createdDate']) if 'createdDate' in api else None,
133
+ 'version': api.get('version'),
134
+ 'minimumCompressionSize': api.get('minimumCompressionSize'),
135
+ 'disableExecuteApiEndpoint': api.get('disableExecuteApiEndpoint'),
136
+ # Set defaults in the transform function
137
+ 'anonymous_access': policy_data.get('internet_accessible', False),
138
+ 'anonymous_actions': policy_data.get('accessible_actions', []),
139
+ # TODO Issue #1452: clarify internet exposure vs anonymous access
140
+ }
141
+ transformed_apis.append(transformed_api)
142
+
143
+ return transformed_apis
147
144
 
148
145
 
149
146
  @timeit
150
- def _load_apigateway_policies(
151
- neo4j_session: neo4j.Session, policies: List, update_tag: int,
147
+ def load_apigateway_rest_apis(
148
+ neo4j_session: neo4j.Session, data: List[Dict], region: str, current_aws_account_id: str,
149
+ aws_update_tag: int,
152
150
  ) -> None:
153
151
  """
154
- Ingest API Gateway REST API policy results into neo4j.
155
- """
156
- ingest_policies = """
157
- UNWIND $policies as policy
158
- MATCH (r:APIGatewayRestAPI) where r.name = policy.api_id
159
- SET r.anonymous_access = (coalesce(r.anonymous_access, false) OR policy.internet_accessible),
160
- r.anonymous_actions = coalesce(r.anonymous_actions, []) + policy.accessible_actions,
161
- r.lastupdated = $UpdateTag
152
+ Ingest API Gateway REST API data into neo4j.
162
153
  """
163
-
164
- neo4j_session.run(
165
- ingest_policies,
166
- policies=policies,
167
- UpdateTag=update_tag,
168
- )
169
-
170
-
171
- def _set_default_values(neo4j_session: neo4j.Session, aws_account_id: str) -> None:
172
- set_defaults = """
173
- MATCH (:AWSAccount{id: $AWS_ID})-[:RESOURCE]->(restApi:APIGatewayRestAPI)
174
- where restApi.anonymous_actions IS NULL
175
- SET restApi.anonymous_access = false, restApi.anonymous_actions = []
176
- """
177
-
178
- neo4j_session.run(
179
- set_defaults,
180
- AWS_ID=aws_account_id,
154
+ load(
155
+ neo4j_session,
156
+ APIGatewayRestAPISchema(),
157
+ data,
158
+ region=region,
159
+ lastupdated=aws_update_tag,
160
+ AWS_ID=current_aws_account_id,
181
161
  )
182
162
 
183
163
 
184
- @timeit
185
- def _load_apigateway_stages(
186
- neo4j_session: neo4j.Session, stages: List, update_tag: int,
187
- ) -> None:
164
+ def transform_apigateway_stages(stages: List[Dict], update_tag: int) -> List[Dict]:
188
165
  """
189
- Ingest the Stage resource details into neo4j.
166
+ Transform API Gateway Stage data for ingestion
190
167
  """
191
- ingest_stages = """
192
- UNWIND $stages_list AS stage
193
- MERGE (s:APIGatewayStage{id: stage.arn})
194
- ON CREATE SET s.firstseen = timestamp(), s.stagename = stage.stageName,
195
- s.createddate = stage.createdDate
196
- SET s.deploymentid = stage.deploymentId,
197
- s.clientcertificateid = stage.clientCertificateId,
198
- s.cacheclusterenabled = stage.cacheClusterEnabled,
199
- s.cacheclusterstatus = stage.cacheClusterStatus,
200
- s.tracingenabled = stage.tracingEnabled,
201
- s.webaclarn = stage.webAclArn,
202
- s.lastupdated = $UpdateTag
203
- WITH s, stage
204
- MATCH (rest_api:APIGatewayRestAPI{id: stage.apiId})
205
- MERGE (rest_api)-[r:ASSOCIATED_WITH]->(s)
206
- ON CREATE SET r.firstseen = timestamp()
207
- SET r.lastupdated = $UpdateTag
208
- """
209
-
210
- # neo4j does not accept datetime objects and values. This loop is used to convert
211
- # these values to string.
168
+ stage_data = []
212
169
  for stage in stages:
213
170
  stage['createdDate'] = str(stage['createdDate'])
214
- stage['arn'] = "arn:aws:apigateway:::" + stage['apiId'] + "/" + stage['stageName']
215
-
216
- neo4j_session.run(
217
- ingest_stages,
218
- stages_list=stages,
219
- UpdateTag=update_tag,
220
- )
171
+ stage['arn'] = f"arn:aws:apigateway:::{stage['apiId']}/{stage['stageName']}"
172
+ stage_data.append(stage)
173
+ return stage_data
221
174
 
222
175
 
223
- @timeit
224
- def _load_apigateway_certificates(
225
- neo4j_session: neo4j.Session, certificates: List, update_tag: int,
226
- ) -> None:
227
- """
228
- Ingest the API Gateway Client Certificate details into neo4j.
176
+ def transform_apigateway_certificates(certificates: List[Dict], update_tag: int) -> List[Dict]:
229
177
  """
230
- ingest_certificates = """
231
- UNWIND $certificates_list as certificate
232
- MERGE (c:APIGatewayClientCertificate{id: certificate.clientCertificateId})
233
- ON CREATE SET c.firstseen = timestamp(), c.createddate = certificate.createdDate
234
- SET c.lastupdated = $UpdateTag, c.expirationdate = certificate.expirationDate
235
- WITH c, certificate
236
- MATCH (stage:APIGatewayStage{id: certificate.stageArn})
237
- MERGE (stage)-[r:HAS_CERTIFICATE]->(c)
238
- ON CREATE SET r.firstseen = timestamp()
239
- SET r.lastupdated = $UpdateTag
178
+ Transform API Gateway Client Certificate data for ingestion
240
179
  """
241
-
242
- # neo4j does not accept datetime objects and values. This loop is used to convert
243
- # these values to string.
180
+ cert_data = []
244
181
  for certificate in certificates:
245
182
  certificate['createdDate'] = str(certificate['createdDate'])
246
183
  certificate['expirationDate'] = str(certificate.get('expirationDate'))
247
- certificate['stageArn'] = "arn:aws:apigateway:::" + certificate['apiId'] + "/" + certificate['stageName']
248
-
249
- neo4j_session.run(
250
- ingest_certificates,
251
- certificates_list=certificates,
252
- UpdateTag=update_tag,
253
- )
254
-
255
-
256
- @timeit
257
- def _load_apigateway_resources(
258
- neo4j_session: neo4j.Session, resources: List, update_tag: int,
259
- ) -> None:
260
- """
261
- Ingest the API Gateway Resource details into neo4j.
262
- """
263
- ingest_resources = """
264
- UNWIND $resources_list AS res
265
- MERGE (s:APIGatewayResource{id: res.id})
266
- ON CREATE SET s.firstseen = timestamp()
267
- SET s.path = res.path,
268
- s.pathpart = res.pathPart,
269
- s.parentid = res.parentId,
270
- s.lastupdated =$UpdateTag
271
- WITH s, res
272
- MATCH (rest_api:APIGatewayRestAPI{id: res.apiId})
273
- MERGE (rest_api)-[r:RESOURCE]->(s)
274
- ON CREATE SET r.firstseen = timestamp()
275
- SET r.lastupdated = $UpdateTag
276
- """
277
-
278
- neo4j_session.run(
279
- ingest_resources,
280
- resources_list=resources,
281
- UpdateTag=update_tag,
282
- )
184
+ certificate['stageArn'] = f"arn:aws:apigateway:::{certificate['apiId']}/{certificate['stageName']}"
185
+ cert_data.append(certificate)
186
+ return cert_data
283
187
 
284
188
 
285
- @timeit
286
- def load_rest_api_details(
287
- neo4j_session: neo4j.Session, stages_certificate_resources: List[Tuple[Any, Any, Any, Any, Any]],
288
- aws_account_id: str, update_tag: int,
289
- ) -> None:
189
+ def transform_rest_api_details(
190
+ stages_certificate_resources: List[Tuple[Any, Any, Any, Any, Any]],
191
+ ) -> Tuple[List[Dict], List[Dict], List[Dict]]:
290
192
  """
291
- Create dictionaries for Stages, Client certificates, policies and Resource resources
292
- so we can import them in a single query
193
+ Transform Stage, Client Certificate, and Resource data for ingestion
293
194
  """
294
195
  stages: List[Dict] = []
295
196
  certificates: List[Dict] = []
296
197
  resources: List[Dict] = []
297
- policies: List = []
298
- for api_id, stage, certificate, resource, policy in stages_certificate_resources:
299
- parsed_policy = parse_policy(api_id, policy)
300
- if parsed_policy is not None:
301
- policies.append(parsed_policy)
198
+
199
+ for api_id, stage, certificate, resource, _ in stages_certificate_resources:
302
200
  if len(stage) > 0:
303
201
  for s in stage:
304
202
  s['apiId'] = api_id
203
+ s['createdDate'] = str(s['createdDate'])
204
+ s['arn'] = f"arn:aws:apigateway:::{api_id}/{s['stageName']}"
305
205
  stages.extend(stage)
206
+
207
+ if certificate:
208
+ certificate['apiId'] = api_id
209
+ certificate['createdDate'] = str(certificate['createdDate'])
210
+ certificate['expirationDate'] = str(certificate.get('expirationDate'))
211
+ certificate['stageArn'] = f"arn:aws:apigateway:::{api_id}/{certificate['stageName']}"
212
+ certificates.append(certificate)
213
+
306
214
  if len(resource) > 0:
307
215
  for r in resource:
308
216
  r['apiId'] = api_id
309
217
  resources.extend(resource)
310
- if certificate:
311
- certificate['apiId'] = api_id
312
- certificates.append(certificate)
313
218
 
314
- # cleanup existing properties
315
- run_cleanup_job(
316
- 'aws_apigateway_details.json',
219
+ return stages, certificates, resources
220
+
221
+
222
+ @timeit
223
+ def load_rest_api_details(
224
+ neo4j_session: neo4j.Session, stages_certificate_resources: List[Tuple[Any, Any, Any, Any, Any]],
225
+ aws_account_id: str, update_tag: int,
226
+ ) -> None:
227
+ """
228
+ Transform and load Stage, Client Certificate, and Resource data
229
+ """
230
+ stages, certificates, resources = transform_rest_api_details(stages_certificate_resources)
231
+
232
+ load(
317
233
  neo4j_session,
318
- {'UPDATE_TAG': update_tag, 'AWS_ID': aws_account_id},
234
+ APIGatewayStageSchema(),
235
+ stages,
236
+ lastupdated=update_tag,
237
+ AWS_ID=aws_account_id,
319
238
  )
320
239
 
321
- _load_apigateway_policies(neo4j_session, policies, update_tag)
322
- _load_apigateway_stages(neo4j_session, stages, update_tag)
323
- _load_apigateway_certificates(neo4j_session, certificates, update_tag)
324
- _load_apigateway_resources(neo4j_session, resources, update_tag)
325
- _set_default_values(neo4j_session, aws_account_id)
240
+ load(
241
+ neo4j_session,
242
+ APIGatewayClientCertificateSchema(),
243
+ certificates,
244
+ lastupdated=update_tag,
245
+ AWS_ID=aws_account_id,
246
+ )
247
+
248
+ load(
249
+ neo4j_session,
250
+ APIGatewayResourceSchema(),
251
+ resources,
252
+ lastupdated=update_tag,
253
+ AWS_ID=aws_account_id,
254
+ )
326
255
 
327
256
 
328
257
  @timeit
@@ -353,7 +282,27 @@ def parse_policy(api_id: str, policy: Policy) -> Optional[Dict[Any, Any]]:
353
282
 
354
283
  @timeit
355
284
  def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
356
- run_cleanup_job('aws_import_apigateway_cleanup.json', neo4j_session, common_job_parameters)
285
+ """
286
+ Delete out-of-date API Gateway resources and relationships.
287
+ Order matters - clean up certificates, stages, and resources before cleaning up the REST APIs they connect to.
288
+ """
289
+ logger.info("Running API Gateway cleanup job.")
290
+
291
+ # Clean up certificates first
292
+ cleanup_job = GraphJob.from_node_schema(APIGatewayClientCertificateSchema(), common_job_parameters)
293
+ cleanup_job.run(neo4j_session)
294
+
295
+ # Then stages
296
+ cleanup_job = GraphJob.from_node_schema(APIGatewayStageSchema(), common_job_parameters)
297
+ cleanup_job.run(neo4j_session)
298
+
299
+ # Then resources
300
+ cleanup_job = GraphJob.from_node_schema(APIGatewayResourceSchema(), common_job_parameters)
301
+ cleanup_job.run(neo4j_session)
302
+
303
+ # Finally REST APIs
304
+ cleanup_job = GraphJob.from_node_schema(APIGatewayRestAPISchema(), common_job_parameters)
305
+ cleanup_job.run(neo4j_session)
357
306
 
358
307
 
359
308
  @timeit
@@ -362,9 +311,23 @@ def sync_apigateway_rest_apis(
362
311
  aws_update_tag: int,
363
312
  ) -> None:
364
313
  rest_apis = get_apigateway_rest_apis(boto3_session, region)
365
- load_apigateway_rest_apis(neo4j_session, rest_apis, region, current_aws_account_id, aws_update_tag)
366
-
367
314
  stages_certificate_resources = get_rest_api_details(boto3_session, rest_apis, region)
315
+
316
+ # Extract policies and transform the data
317
+ policies = []
318
+ for api_id, _, _, _, policy in stages_certificate_resources:
319
+ parsed_policy = parse_policy(api_id, policy)
320
+ if parsed_policy is not None:
321
+ policies.append(parsed_policy)
322
+
323
+ transformed_apis = transform_apigateway_rest_apis(
324
+ rest_apis,
325
+ policies,
326
+ region,
327
+ current_aws_account_id,
328
+ aws_update_tag,
329
+ )
330
+ load_apigateway_rest_apis(neo4j_session, transformed_apis, region, current_aws_account_id, aws_update_tag)
368
331
  load_rest_api_details(neo4j_session, stages_certificate_resources, current_aws_account_id, aws_update_tag)
369
332
 
370
333
 
@@ -8,8 +8,8 @@ import neo4j
8
8
  from botocore.exceptions import ClientError
9
9
 
10
10
  from cartography.client.core.tx import load
11
+ from cartography.client.core.tx import read_list_of_values_tx
11
12
  from cartography.graph.job import GraphJob
12
- from cartography.intel.aws.ec2 import get_ec2_regions
13
13
  from cartography.intel.aws.ec2.util import get_botocore_config
14
14
  from cartography.models.aws.ec2.images import EC2ImageSchema
15
15
  from cartography.util import aws_handle_regions
@@ -21,22 +21,26 @@ logger = logging.getLogger(__name__)
21
21
  @timeit
22
22
  def get_images_in_use(neo4j_session: neo4j.Session, region: str, current_aws_account_id: str) -> List[str]:
23
23
  get_images_query = """
24
+ CALL {
24
25
  MATCH (:AWSAccount{id: $AWS_ACCOUNT_ID})-[:RESOURCE]->(i:EC2Instance)
25
- WHERE i.region = $Region
26
- RETURN DISTINCT(i.imageid) as image
27
- UNION
26
+ WHERE i.region = $Region AND i.imageid IS NOT NULL
27
+ RETURN i.imageid AS image
28
+ UNION ALL
28
29
  MATCH (:AWSAccount{id: $AWS_ACCOUNT_ID})-[:RESOURCE]->(lc:LaunchConfiguration)
29
- WHERE lc.region = $Region
30
- RETURN DISTINCT(lc.image_id) as image
31
- UNION
30
+ WHERE lc.region = $Region AND lc.image_id IS NOT NULL
31
+ RETURN lc.image_id AS image
32
+ UNION ALL
32
33
  MATCH (:AWSAccount{id: $AWS_ACCOUNT_ID})-[:RESOURCE]->(ltv:LaunchTemplateVersion)
33
- WHERE ltv.region = $Region
34
- RETURN DISTINCT(ltv.image_id) as image
34
+ WHERE ltv.region = $Region AND ltv.image_id IS NOT NULL
35
+ RETURN ltv.image_id AS image
36
+ }
37
+ RETURN DISTINCT image;
35
38
  """
36
- results = neo4j_session.run(get_images_query, AWS_ACCOUNT_ID=current_aws_account_id, Region=region)
37
- images = []
38
- for r in results:
39
- images.append(r['image'])
39
+ result = read_list_of_values_tx(
40
+ neo4j_session, get_images_query,
41
+ AWS_ACCOUNT_ID=current_aws_account_id, Region=region,
42
+ )
43
+ images = [str(image) for image in result]
40
44
  return images
41
45
 
42
46
 
@@ -45,39 +49,23 @@ def get_images_in_use(neo4j_session: neo4j.Session, region: str, current_aws_acc
45
49
  def get_images(boto3_session: boto3.session.Session, region: str, image_ids: List[str]) -> List[Dict]:
46
50
  client = boto3_session.client('ec2', region_name=region, config=get_botocore_config())
47
51
  images = []
52
+ self_images = []
48
53
  try:
49
54
  self_images = client.describe_images(Owners=['self'])['Images']
50
- images.extend(self_images)
51
- except ClientError as e:
52
- logger.warning(f"Failed to retrieve private images for region - {region}. Error - {e}")
53
- try:
54
- if image_ids:
55
- image_ids = [image_id for image_id in image_ids if image_id is not None]
56
- images_in_use = client.describe_images(ImageIds=image_ids)['Images']
57
- # Ensure we're not adding duplicates
58
- _ids = [image["ImageId"] for image in images]
59
- for image in images_in_use:
60
- if image["ImageId"] not in _ids:
61
- images.append(image)
62
- _ids.append(image["ImageId"])
63
- # Handle cross region image ids
64
- if len(_ids) != len(image_ids):
65
- logger.info("Attempting to retrieve images from other regions")
66
- pending_ids = [image_id for image_id in image_ids if image_id not in _ids]
67
- all_regions = get_ec2_regions(boto3_session)
68
- clients = {
69
- other_region: boto3_session.client('ec2', region_name=other_region, config=get_botocore_config())
70
- for other_region in all_regions if other_region != region
71
- }
72
- for other_region, client in clients.items():
73
- for _id in pending_ids:
74
- try:
75
- pending_image = client.describe_images(ImageIds=[_id])['Images']
76
- images.extend(pending_image)
77
- except ClientError as e:
78
- logger.warning(f"Image {id} could not be found at region - {other_region}. Error - {e}")
79
55
  except ClientError as e:
80
- logger.warning(f"Failed to retrieve public images for region - {region}. Error - {e}")
56
+ logger.warning(f"Failed retrieve self owned images for region - {region}. Error - {e}")
57
+ images.extend(self_images)
58
+ if image_ids:
59
+ self_image_ids = {image['ImageId'] for image in images}
60
+ # Go one by one to avoid losing all images if one fails
61
+ for image in image_ids:
62
+ if image in self_image_ids:
63
+ continue
64
+ try:
65
+ public_images = client.describe_images(ImageIds=[image])['Images']
66
+ images.extend(public_images)
67
+ except ClientError as e:
68
+ logger.warning(f"Failed retrieve image id {image} for region - {region}. Error - {e}")
81
69
  return images
82
70
 
83
71
 
@@ -0,0 +1,47 @@
1
+ from dataclasses import dataclass
2
+
3
+ from cartography.models.core.common import PropertyRef
4
+ from cartography.models.core.nodes import CartographyNodeProperties
5
+ from cartography.models.core.nodes import CartographyNodeSchema
6
+ from cartography.models.core.relationships import CartographyRelProperties
7
+ from cartography.models.core.relationships import CartographyRelSchema
8
+ from cartography.models.core.relationships import LinkDirection
9
+ from cartography.models.core.relationships import make_target_node_matcher
10
+ from cartography.models.core.relationships import TargetNodeMatcher
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class APIGatewayRestAPINodeProperties(CartographyNodeProperties):
15
+ id: PropertyRef = PropertyRef('id', extra_index=True)
16
+ createddate: PropertyRef = PropertyRef('createdDate')
17
+ version: PropertyRef = PropertyRef('version')
18
+ minimumcompressionsize: PropertyRef = PropertyRef('minimumCompressionSize')
19
+ disableexecuteapiendpoint: PropertyRef = PropertyRef('disableExecuteApiEndpoint')
20
+ region: PropertyRef = PropertyRef('region', set_in_kwargs=True)
21
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
22
+ anonymous_access: PropertyRef = PropertyRef('anonymous_access')
23
+ anonymous_actions: PropertyRef = PropertyRef('anonymous_actions')
24
+
25
+
26
+ @dataclass(frozen=True)
27
+ class APIGatewayRestAPIToAwsAccountRelProperties(CartographyRelProperties):
28
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
29
+
30
+
31
+ @dataclass(frozen=True)
32
+ # (:APIGatewayRestAPI)<-[:RESOURCE]-(:AWSAccount)
33
+ class APIGatewayRestAPIToAWSAccount(CartographyRelSchema):
34
+ target_node_label: str = 'AWSAccount'
35
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
36
+ {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
37
+ )
38
+ direction: LinkDirection = LinkDirection.INWARD
39
+ rel_label: str = "RESOURCE"
40
+ properties: APIGatewayRestAPIToAwsAccountRelProperties = APIGatewayRestAPIToAwsAccountRelProperties()
41
+
42
+
43
+ @dataclass(frozen=True)
44
+ class APIGatewayRestAPISchema(CartographyNodeSchema):
45
+ label: str = 'APIGatewayRestAPI'
46
+ properties: APIGatewayRestAPINodeProperties = APIGatewayRestAPINodeProperties()
47
+ sub_resource_relationship: APIGatewayRestAPIToAWSAccount = APIGatewayRestAPIToAWSAccount()
@@ -0,0 +1,66 @@
1
+ from dataclasses import dataclass
2
+
3
+ from cartography.models.core.common import PropertyRef
4
+ from cartography.models.core.nodes import CartographyNodeProperties
5
+ from cartography.models.core.nodes import CartographyNodeSchema
6
+ from cartography.models.core.relationships import CartographyRelProperties
7
+ from cartography.models.core.relationships import CartographyRelSchema
8
+ from cartography.models.core.relationships import LinkDirection
9
+ from cartography.models.core.relationships import make_target_node_matcher
10
+ from cartography.models.core.relationships import OtherRelationships
11
+ from cartography.models.core.relationships import TargetNodeMatcher
12
+
13
+
14
+ @dataclass(frozen=True)
15
+ class APIGatewayClientCertificateNodeProperties(CartographyNodeProperties):
16
+ id: PropertyRef = PropertyRef('clientCertificateId')
17
+ createddate: PropertyRef = PropertyRef('createdDate')
18
+ expirationdate: PropertyRef = PropertyRef('expirationDate')
19
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
20
+
21
+
22
+ @dataclass(frozen=True)
23
+ class APIGatewayClientCertificateToStageRelProperties(CartographyRelProperties):
24
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
25
+
26
+
27
+ @dataclass(frozen=True)
28
+ class CertToStageRelProps(CartographyRelProperties):
29
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
30
+
31
+
32
+ @dataclass(frozen=True)
33
+ # (:APIGatewayStage)-[:HAS_CERTIFICATE]->(:APIGatewayClientCertificate)
34
+ class APIGatewayClientCertificateToStage(CartographyRelSchema):
35
+ target_node_label: str = 'APIGatewayStage'
36
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
37
+ {'id': PropertyRef('stageArn')},
38
+ )
39
+ direction: LinkDirection = LinkDirection.INWARD
40
+ rel_label: str = "HAS_CERTIFICATE"
41
+ properties: CertToStageRelProps = CertToStageRelProps()
42
+
43
+
44
+ @dataclass(frozen=True)
45
+ class CertToAccountRelProps(CartographyRelProperties):
46
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
47
+
48
+
49
+ @dataclass(frozen=True)
50
+ # (:APIGatewayClientCertificate)<-[:RESOURCE]-(:AWSAccount)
51
+ class APIGatewayClientCertificateToAWSAccount(CartographyRelSchema):
52
+ target_node_label: str = 'AWSAccount'
53
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
54
+ {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
55
+ )
56
+ direction: LinkDirection = LinkDirection.INWARD
57
+ rel_label: str = "RESOURCE"
58
+ properties: CertToAccountRelProps = CertToAccountRelProps()
59
+
60
+
61
+ @dataclass(frozen=True)
62
+ class APIGatewayClientCertificateSchema(CartographyNodeSchema):
63
+ label: str = 'APIGatewayClientCertificate'
64
+ properties: APIGatewayClientCertificateNodeProperties = APIGatewayClientCertificateNodeProperties()
65
+ sub_resource_relationship: APIGatewayClientCertificateToAWSAccount = APIGatewayClientCertificateToAWSAccount()
66
+ other_relationships: OtherRelationships = OtherRelationships([APIGatewayClientCertificateToStage()])
@@ -0,0 +1,62 @@
1
+ from dataclasses import dataclass
2
+
3
+ from cartography.models.core.common import PropertyRef
4
+ from cartography.models.core.nodes import CartographyNodeProperties
5
+ from cartography.models.core.nodes import CartographyNodeSchema
6
+ from cartography.models.core.relationships import CartographyRelProperties
7
+ from cartography.models.core.relationships import CartographyRelSchema
8
+ from cartography.models.core.relationships import LinkDirection
9
+ from cartography.models.core.relationships import make_target_node_matcher
10
+ from cartography.models.core.relationships import OtherRelationships
11
+ from cartography.models.core.relationships import TargetNodeMatcher
12
+
13
+
14
+ @dataclass(frozen=True)
15
+ class APIGatewayResourceNodeProperties(CartographyNodeProperties):
16
+ id: PropertyRef = PropertyRef('id')
17
+ path: PropertyRef = PropertyRef('path')
18
+ pathpart: PropertyRef = PropertyRef('pathPart')
19
+ parentid: PropertyRef = PropertyRef('parentId')
20
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
21
+
22
+
23
+ @dataclass(frozen=True)
24
+ class APIGatewayResourceToRestAPIRelProperties(CartographyRelProperties):
25
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
26
+
27
+
28
+ @dataclass(frozen=True)
29
+ # (:APIGatewayResource)<-[:RESOURCE]-(:APIGatewayRestAPI)
30
+ class APIGatewayResourceToRestAPI(CartographyRelSchema):
31
+ target_node_label: str = 'APIGatewayRestAPI'
32
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
33
+ {'id': PropertyRef('apiId')},
34
+ )
35
+ direction: LinkDirection = LinkDirection.INWARD
36
+ rel_label: str = "RESOURCE"
37
+ properties: APIGatewayResourceToRestAPIRelProperties = APIGatewayResourceToRestAPIRelProperties()
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class APIGatewayResourceToAwsAccountRelProperties(CartographyRelProperties):
42
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
43
+
44
+
45
+ @dataclass(frozen=True)
46
+ # (:APIGatewayResource)<-[:RESOURCE]-(:AWSAccount)
47
+ class APIGatewayResourceToAWSAccount(CartographyRelSchema):
48
+ target_node_label: str = 'AWSAccount'
49
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
50
+ {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
51
+ )
52
+ direction: LinkDirection = LinkDirection.INWARD
53
+ rel_label: str = "RESOURCE"
54
+ properties: APIGatewayResourceToAwsAccountRelProperties = APIGatewayResourceToAwsAccountRelProperties()
55
+
56
+
57
+ @dataclass(frozen=True)
58
+ class APIGatewayResourceSchema(CartographyNodeSchema):
59
+ label: str = 'APIGatewayResource'
60
+ properties: APIGatewayResourceNodeProperties = APIGatewayResourceNodeProperties()
61
+ sub_resource_relationship: APIGatewayResourceToAWSAccount = APIGatewayResourceToAWSAccount()
62
+ other_relationships: OtherRelationships = OtherRelationships([APIGatewayResourceToRestAPI()])
@@ -0,0 +1,67 @@
1
+ from dataclasses import dataclass
2
+
3
+ from cartography.models.core.common import PropertyRef
4
+ from cartography.models.core.nodes import CartographyNodeProperties
5
+ from cartography.models.core.nodes import CartographyNodeSchema
6
+ from cartography.models.core.relationships import CartographyRelProperties
7
+ from cartography.models.core.relationships import CartographyRelSchema
8
+ from cartography.models.core.relationships import LinkDirection
9
+ from cartography.models.core.relationships import make_target_node_matcher
10
+ from cartography.models.core.relationships import OtherRelationships
11
+ from cartography.models.core.relationships import TargetNodeMatcher
12
+
13
+
14
+ @dataclass(frozen=True)
15
+ class APIGatewayStageNodeProperties(CartographyNodeProperties):
16
+ id: PropertyRef = PropertyRef('arn')
17
+ stagename: PropertyRef = PropertyRef('stageName')
18
+ createddate: PropertyRef = PropertyRef('createdDate')
19
+ deploymentid: PropertyRef = PropertyRef('deploymentId')
20
+ clientcertificateid: PropertyRef = PropertyRef('clientCertificateId')
21
+ cacheclusterenabled: PropertyRef = PropertyRef('cacheClusterEnabled')
22
+ cacheclusterstatus: PropertyRef = PropertyRef('cacheClusterStatus')
23
+ tracingenabled: PropertyRef = PropertyRef('tracingEnabled')
24
+ webaclarn: PropertyRef = PropertyRef('webAclArn')
25
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
26
+
27
+
28
+ @dataclass(frozen=True)
29
+ class APIGatewayStageToRestAPIRelProperties(CartographyRelProperties):
30
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
31
+
32
+
33
+ @dataclass(frozen=True)
34
+ # (:APIGatewayStage)<-[:ASSOCIATED_WITH]-(:APIGatewayRestAPI)
35
+ class APIGatewayStageToRestAPI(CartographyRelSchema):
36
+ target_node_label: str = 'APIGatewayRestAPI'
37
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
38
+ {'id': PropertyRef('apiId')},
39
+ )
40
+ direction: LinkDirection = LinkDirection.INWARD
41
+ rel_label: str = "ASSOCIATED_WITH"
42
+ properties: APIGatewayStageToRestAPIRelProperties = APIGatewayStageToRestAPIRelProperties()
43
+
44
+
45
+ @dataclass(frozen=True)
46
+ class APIGatewayStageToAwsAccountRelProperties(CartographyRelProperties):
47
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
48
+
49
+
50
+ @dataclass(frozen=True)
51
+ # (:APIGatewayStage)<-[:RESOURCE]-(:AWSAccount)
52
+ class APIGatewayStageToAWSAccount(CartographyRelSchema):
53
+ target_node_label: str = 'AWSAccount'
54
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
55
+ {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
56
+ )
57
+ direction: LinkDirection = LinkDirection.INWARD
58
+ rel_label: str = "RESOURCE"
59
+ properties: APIGatewayStageToAwsAccountRelProperties = APIGatewayStageToAwsAccountRelProperties()
60
+
61
+
62
+ @dataclass(frozen=True)
63
+ class APIGatewayStageSchema(CartographyNodeSchema):
64
+ label: str = 'APIGatewayStage'
65
+ properties: APIGatewayStageNodeProperties = APIGatewayStageNodeProperties()
66
+ sub_resource_relationship: APIGatewayStageToAWSAccount = APIGatewayStageToAWSAccount()
67
+ other_relationships: OtherRelationships = OtherRelationships([APIGatewayStageToRestAPI()])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: cartography
3
- Version: 0.99.0rc1
3
+ Version: 0.100.0rc1
4
4
  Summary: Explore assets and their relationships across your technical infrastructure.
5
5
  Maintainer: Cartography Contributors
6
6
  License: apache2
@@ -62,10 +62,16 @@ Requires-Dist: pytest-mock; extra == "dev"
62
62
  Requires-Dist: pytest-cov==2.10.0; extra == "dev"
63
63
  Requires-Dist: pytest-rerunfailures; extra == "dev"
64
64
  Requires-Dist: types-PyYAML; extra == "dev"
65
- Requires-Dist: types-requests<2.31.0.7; extra == "dev"
65
+ Requires-Dist: types-requests<2.32.0.20241017; extra == "dev"
66
66
 
67
67
  ![Cartography](docs/root/images/logo-horizontal.png)
68
68
 
69
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/cartography-cncf/cartography/badge)](https://scorecard.dev/viewer/?uri=github.com/cartography-cncf/cartography)
70
+ [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9637/badge)](https://www.bestpractices.dev/projects/9637)
71
+ ![build](https://github.com/cartography-cncf/cartography/actions/workflows/publish-to-ghcr-and-pypi.yml/badge.svg)
72
+
73
+
74
+
69
75
  Cartography is a Python tool that consolidates infrastructure assets and the relationships between them in an intuitive graph view powered by a [Neo4j](https://www.neo4j.com) database.
70
76
 
71
77
  ![Visualization of RDS nodes and AWS nodes](docs/root/images/accountsandrds.png)
@@ -147,9 +153,9 @@ Directly querying Neo4j is already very useful as a sort of "swiss army knife" f
147
153
  ## Community
148
154
 
149
155
  - Hang out with us on Slack: Join the CNCF Slack workspace [here](https://communityinviter.com/apps/cloud-native/cncf), and then join the `#cartography` channel.
150
- - Talk to us and see what we're working on at our [monthly community meeting](https://calendar.google.com/calendar/embed?src=lyft.com_p10o6ceuiieq9sqcn1ef61v1io%40group.calendar.google.com&ctz=America%2FLos_Angeles).
156
+ - Talk to us and see what we're working on at our [monthly community meeting](https://zoom-lfx.platform.linuxfoundation.org/meetings/cartography?view=week).
151
157
  - Meeting minutes are [here](https://docs.google.com/document/d/1VyRKmB0dpX185I15BmNJZpfAJ_Ooobwz0U1WIhjDxvw).
152
- - Recorded videos are posted [here](https://www.youtube.com/playlist?list=PLMga2YJvAGzidUWJB_fnG7EHI4wsDDsE1).
158
+ - Recorded videos from before 2025 are posted [here](https://www.youtube.com/playlist?list=PLMga2YJvAGzidUWJB_fnG7EHI4wsDDsE1).
153
159
 
154
160
  ## License
155
161
 
@@ -1,6 +1,6 @@
1
1
  cartography/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  cartography/__main__.py,sha256=JftXT_nUPkqcEh8uxCCT4n-OyHYqbldEgrDS-4ygy0U,101
3
- cartography/_version.py,sha256=hM9CRVuInASxNswzZ4txXUj1H_ZnoY8bgRIKCsEw0Oc,416
3
+ cartography/_version.py,sha256=m60nwdmRfNS_e1bH0LUuweYWYEmDYMPRcAZovFm1Lq4,418
4
4
  cartography/cli.py,sha256=LPjeOkx-cKhRkuhqMicB-0X3SHOjLXxEeGqsp2FtpC0,33285
5
5
  cartography/config.py,sha256=ZcadsKmooAkti9Kv0eDl8Ec1PcZDu3lWobtNaCnwY3k,11872
6
6
  cartography/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -31,10 +31,8 @@ cartography/data/jobs/analysis/gcp_gke_basic_auth.json,sha256=qLkrw1eZvV9ETtkIQN
31
31
  cartography/data/jobs/analysis/gsuite_human_link.json,sha256=ArWA51fNIeeXwYiroJbKnuqN8y-TLrndOq0ZdC9q5os,541
32
32
  cartography/data/jobs/cleanup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
33
  cartography/data/jobs/cleanup/aws_account_cleanup.json,sha256=DEB4h6Z4NSpYaLXECPhNk8HHbT0XNlqUA01pXIskBxc,473
34
- cartography/data/jobs/cleanup/aws_apigateway_details.json,sha256=rh7cMTebjyUoEu_s7nKl3m-GLQ3gXgw0s3kMJfWKjro,323
35
34
  cartography/data/jobs/cleanup/aws_dns_cleanup.json,sha256=H5uMZV4tN6HcjTYwh2I1dENzNGqu2D2Rs2q-5CK5e0Y,3498
36
35
  cartography/data/jobs/cleanup/aws_import_account_access_key_cleanup.json,sha256=UCrAXf-8yQIoUa843VLLTpqrSpNa753c1cxzg32oqU0,737
37
- cartography/data/jobs/cleanup/aws_import_apigateway_cleanup.json,sha256=wCV95ydo3dmlhK7VrDrxCqrP6dbhCCMTzcz_qaJQ4Jo,2189
38
36
  cartography/data/jobs/cleanup/aws_import_config_cleanup.json,sha256=VCAJjEnFcQUR16VxKdpsOkBJEnhMuLk-7Kgm_p9k1NM,754
39
37
  cartography/data/jobs/cleanup/aws_import_ec2_launch_configurations_cleanup.json,sha256=x9IIzb9Sr1353ygkA-qqUUbZS9XO2v3GzUHe-0J4Pw8,281
40
38
  cartography/data/jobs/cleanup/aws_import_ec2_security_groupinfo_cleanup.json,sha256=CackEgSs1PN15pTg8oIdS0amB-n-PsKODLAaqC3gf_A,1183
@@ -143,7 +141,7 @@ cartography/intel/analysis.py,sha256=gHtN42NqqLL1G5MOm2Q6rMyg-V5lU_wqbnKp5hbOOao
143
141
  cartography/intel/create_indexes.py,sha256=HM2jB2v3NZvGqgVDtNoBQRVpkei_JXcYXqM14w8Rjss,741
144
142
  cartography/intel/dns.py,sha256=M-WSiGQoxWZsl0sg-2SDR8OD8e1Rexkt2Tbb2OpeioA,5596
145
143
  cartography/intel/aws/__init__.py,sha256=siRhVNypfGxMPNIXHSjfYbLX9qlB6RYyN6aWX64N-t8,11076
146
- cartography/intel/aws/apigateway.py,sha256=aTUVjpAksfLJwq_ttye8NWt5LMkCV8vKyXbPW4gN7-U,12736
144
+ cartography/intel/aws/apigateway.py,sha256=w4QdxlwnVegKKsZFfoI36i-FGlIUjzxzaayZyz9oQvM,11654
147
145
  cartography/intel/aws/config.py,sha256=wrZbz7bc8vImLmRvTLkPcWnjjPzk3tOG4bB_BFS2lq8,7329
148
146
  cartography/intel/aws/dynamodb.py,sha256=LZ6LGNThLi0zC3eLMq2JN3mwiSwZeaH58YQQHvsXMGE,5013
149
147
  cartography/intel/aws/ecr.py,sha256=9yK8bXnXBJHW_AOalATjqfC4GTpR9pilpDScla4EFuY,6624
@@ -172,7 +170,7 @@ cartography/intel/aws/ssm.py,sha256=IDOYa8v2FgziU8nBOZ7wyDG4o_nFYshbB-si9Ut_9Zc,
172
170
  cartography/intel/aws/ec2/__init__.py,sha256=IDK2Yap7mllK_ab6yVMLXatJ94znIkn-szv5RJP5fbo,346
173
171
  cartography/intel/aws/ec2/auto_scaling_groups.py,sha256=ylfks8_oC0-fVMnToFbmRcbKdEN0H17LlN1-ZqW6ULc,8148
174
172
  cartography/intel/aws/ec2/elastic_ip_addresses.py,sha256=0k4NwS73VyWbEj5jXvSkaq2RNvmAlBlrN-UKa_Bj0uk,3957
175
- cartography/intel/aws/ec2/images.py,sha256=vxkuh0zQLqtj6DjIRrcQQwgFLhn5mBNQzZW-gg8UFNg,4919
173
+ cartography/intel/aws/ec2/images.py,sha256=SLoxcy_PQgNomVMDMdutm0zXJCOLosiHJlN63YQPA0k,3973
176
174
  cartography/intel/aws/ec2/instances.py,sha256=uI8eVJmeEybS8y_T8CVKAkwxJyVDCH7sbuEJYeWGSWY,12468
177
175
  cartography/intel/aws/ec2/internet_gateways.py,sha256=dI-4-85_3DGGZZBcY_DN6XqESx9P26S6jKok314lcnQ,2883
178
176
  cartography/intel/aws/ec2/key_pairs.py,sha256=g4imIo_5jk8upq9J4--erg-OZXG2i3cJMe6SnNCYj9s,2635
@@ -280,6 +278,10 @@ cartography/intel/snipeit/user.py,sha256=hm9v_p29bphHtGe9LKVo1FD_rQcbCigrCRf8Ysm
280
278
  cartography/intel/snipeit/util.py,sha256=fXlzdFQXm01Oaa2REYNN7x3y3k2l3zCVhf_BxcRUELY,1040
281
279
  cartography/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
282
280
  cartography/models/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
281
+ cartography/models/aws/apigateway.py,sha256=NTzaHlZVGBWv9GNWoHDOgMUt53HN9xO1E06s9RPj7Ek,2262
282
+ cartography/models/aws/apigatewaycertificate.py,sha256=xNjB2wDtW16jo1S4cPYEjU3BUttjQvW8TysrBVpuNnw,2924
283
+ cartography/models/aws/apigatewayresource.py,sha256=qj9OYoDCoAtw4olRgmhfhdQ1Y6ESq14n-mRr2gzUgfI,2760
284
+ cartography/models/aws/apigatewaystage.py,sha256=C1ntCj52iHyyR4APxeYJootvICMk4FVOovvoluL8lIM,3083
283
285
  cartography/models/aws/emr.py,sha256=TkuwoZnw_VHbJ5bwkac7-ZfwSLe_TeK3gxkuwGQOUk4,3037
284
286
  cartography/models/aws/dynamodb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
285
287
  cartography/models/aws/dynamodb/gsi.py,sha256=KYsHJpSgrTQndZGIdKAi5MjgvUne2iNvqTr29BDzI14,3021
@@ -354,9 +356,9 @@ cartography/models/snipeit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
354
356
  cartography/models/snipeit/asset.py,sha256=FyRAaeXuZjMy0eUQcSDFcgEAF5lbLMlvqp1Tv9d3Lv4,3238
355
357
  cartography/models/snipeit/tenant.py,sha256=p4rFnpNNuF1W5ilGBbexDaETWTwavfb38RcQGoImkQI,679
356
358
  cartography/models/snipeit/user.py,sha256=MsB4MiCVNTH6JpESime7cOkB89autZOXQpL6Z0l7L6o,2113
357
- cartography-0.99.0rc1.dist-info/LICENSE,sha256=kvLEBRYaQ1RvUni6y7Ti9uHeooqnjPoo6n_-0JO1ETc,11351
358
- cartography-0.99.0rc1.dist-info/METADATA,sha256=TxsWkL6peNqG6dfFXb0K81KUFsOzJToalPKCgbQwRbI,11473
359
- cartography-0.99.0rc1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
360
- cartography-0.99.0rc1.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
361
- cartography-0.99.0rc1.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
362
- cartography-0.99.0rc1.dist-info/RECORD,,
359
+ cartography-0.100.0rc1.dist-info/LICENSE,sha256=kvLEBRYaQ1RvUni6y7Ti9uHeooqnjPoo6n_-0JO1ETc,11351
360
+ cartography-0.100.0rc1.dist-info/METADATA,sha256=go8iGhWQYwh93GnkZX-Ut4_epIBTQL7e1Xrpz7Y8k-o,11860
361
+ cartography-0.100.0rc1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
362
+ cartography-0.100.0rc1.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
363
+ cartography-0.100.0rc1.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
364
+ cartography-0.100.0rc1.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- {
2
- "statements": [
3
- {
4
- "query": "MATCH (:AWSAccount{id: $AWS_ID})-[:RESOURCE]->(s:RestAPI) WHERE s.anonymous_access IS NOT NULL\n WITH s LIMIT $LIMIT_SIZE\nREMOVE s.anonymous_access, s.anonymous_actions",
5
- "iterative": true,
6
- "iterationsize": 100
7
- }
8
- ],
9
- "name": "AWS APIGateway Exposure Details"
10
- }
@@ -1,45 +0,0 @@
1
- {
2
- "statements": [
3
- {
4
- "query": "MATCH (n:APIGatewayClientCertificate)<-[:HAS_CERTIFICATE]-(:APIGatewayStage)<-[:ASSOCIATED_WITH]-(:APIGatewayRestAPI)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ID}) WHERE n.lastupdated <> $UPDATE_TAG WITH n LIMIT $LIMIT_SIZE DETACH DELETE (n)",
5
- "iterative": true,
6
- "iterationsize": 100
7
- },
8
- {
9
- "query": "MATCH (:APIGatewayClientCertificate)<-[r:HAS_CERTIFICATE]-(:APIGatewayStage)<-[:ASSOCIATED_WITH]-(:APIGatewayRestAPI)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ID}) WHERE r.lastupdated <> $UPDATE_TAG WITH r LIMIT $LIMIT_SIZE DELETE (r)",
10
- "iterative": true,
11
- "iterationsize": 100
12
- },
13
- {
14
- "query": "MATCH (n:APIGatewayStage)<-[:ASSOCIATED_WITH]-(:APIGatewayRestAPI)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ID}) WHERE n.lastupdated <> $UPDATE_TAG WITH n LIMIT $LIMIT_SIZE DETACH DELETE (n)",
15
- "iterative": true,
16
- "iterationsize": 100
17
- },
18
- {
19
- "query": "MATCH (:APIGatewayStage)<-[r:ASSOCIATED_WITH]-(:APIGatewayRestAPI)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ID}) WHERE r.lastupdated <> $UPDATE_TAG WITH r LIMIT $LIMIT_SIZE DELETE (r)",
20
- "iterative": true,
21
- "iterationsize": 100
22
- },
23
- {
24
- "query": "MATCH (n:APIGatewayResource)<-[:RESOURCE]-(:APIGatewayRestAPI)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ID}) WHERE n.lastupdated <> $UPDATE_TAG WITH n LIMIT $LIMIT_SIZE DETACH DELETE (n)",
25
- "iterative": true,
26
- "iterationsize": 100
27
- },
28
- {
29
- "query": "MATCH (:APIGatewayResource)<-[r:RESOURCE]-(:APIGatewayRestAPI)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ID}) WHERE r.lastupdated <> $UPDATE_TAG WITH r LIMIT $LIMIT_SIZE DELETE (r)",
30
- "iterative": true,
31
- "iterationsize": 100
32
- },
33
- {
34
- "query": "MATCH (n:APIGatewayRestAPI)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ID}) WHERE n.lastupdated <> $UPDATE_TAG WITH n LIMIT $LIMIT_SIZE DETACH DELETE (n)",
35
- "iterative": true,
36
- "iterationsize": 100
37
- },
38
- {
39
- "query": "MATCH (:APIGatewayRestAPI)<-[r:RESOURCE]-(:AWSAccount{id: $AWS_ID}) WHERE r.lastupdated <> $UPDATE_TAG WITH r LIMIT $LIMIT_SIZE DELETE (r)",
40
- "iterative": true,
41
- "iterationsize": 100
42
- }
43
- ],
44
- "name": "cleanup APIGateway"
45
- }