cartography 0.97.0__py3-none-any.whl → 0.98.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.

@@ -161,12 +161,8 @@ CREATE INDEX IF NOT EXISTS FOR (n:GCPSubnet) ON (n.id);
161
161
  CREATE INDEX IF NOT EXISTS FOR (n:GCPSubnet) ON (n.lastupdated);
162
162
  CREATE INDEX IF NOT EXISTS FOR (n:GCPVpc) ON (n.id);
163
163
  CREATE INDEX IF NOT EXISTS FOR (n:GCPVpc) ON (n.lastupdated);
164
- CREATE INDEX IF NOT EXISTS FOR (n:GitHubOrganization) ON (n.id);
165
- CREATE INDEX IF NOT EXISTS FOR (n:GitHubOrganization) ON (n.lastupdated);
166
164
  CREATE INDEX IF NOT EXISTS FOR (n:GitHubRepository) ON (n.id);
167
165
  CREATE INDEX IF NOT EXISTS FOR (n:GitHubRepository) ON (n.lastupdated);
168
- CREATE INDEX IF NOT EXISTS FOR (n:GitHubUser) ON (n.id);
169
- CREATE INDEX IF NOT EXISTS FOR (n:GitHubUser) ON (n.lastupdated);
170
166
  CREATE INDEX IF NOT EXISTS FOR (n:GKECluster) ON (n.id);
171
167
  CREATE INDEX IF NOT EXISTS FOR (n:GKECluster) ON (n.lastupdated);
172
168
  CREATE INDEX IF NOT EXISTS FOR (n:GSuiteGroup) ON (n.email);
@@ -1,12 +1,27 @@
1
1
  {
2
2
  "statements": [
3
3
  {
4
- "query": "MATCH (n) where n.exposed_internet IS NOT NULL AND labels(n) IN ['AutoScalingGroup', 'EC2Instance', 'LoadBalancer', 'LoadBalancerV2'] WITH n LIMIT $LIMIT_SIZE REMOVE n.exposed_internet, n.exposed_internet_type return COUNT(*) as TotalCompleted",
4
+ "query": "MATCH (n:AutoScalingGroup) where n.exposed_internet IS NOT NULL WITH n LIMIT $LIMIT_SIZE REMOVE n.exposed_internet, n.exposed_internet_type",
5
5
  "iterative": true,
6
6
  "iterationsize": 1000
7
7
  },
8
8
  {
9
- "query": "MATCH (:IpRange{id: '0.0.0.0/0'})-[:MEMBER_OF_IP_RULE]->(:IpPermissionInbound)-[:MEMBER_OF_EC2_SECURITY_GROUP]->(group:EC2SecurityGroup)<-[:MEMBER_OF_EC2_SECURITY_GROUP|NETWORK_INTERFACE*..2]-(instance:EC2Instance)\nWITH instance\nWHERE (instance.publicipaddress IS NOT NULL) AND (instance.exposed_internet_type IS NULL) OR (NOT 'direct' IN instance.exposed_internet_type)\nSET instance.exposed_internet = true, instance.exposed_internet_type = coalesce(instance.exposed_internet_type , []) + 'direct';",
9
+ "query": "MATCH (n:EC2Instance) where n.exposed_internet IS NOT NULL WITH n LIMIT $LIMIT_SIZE REMOVE n.exposed_internet, n.exposed_internet_type",
10
+ "iterative": true,
11
+ "iterationsize": 1000
12
+ },
13
+ {
14
+ "query": "MATCH (n:LoadBalancer) where n.exposed_internet IS NOT NULL WITH n LIMIT $LIMIT_SIZE REMOVE n.exposed_internet, n.exposed_internet_type",
15
+ "iterative": true,
16
+ "iterationsize": 1000
17
+ },
18
+ {
19
+ "query": "MATCH (n:LoadBalancerV2) where n.exposed_internet IS NOT NULL WITH n LIMIT $LIMIT_SIZE REMOVE n.exposed_internet, n.exposed_internet_type",
20
+ "iterative": true,
21
+ "iterationsize": 1000
22
+ },
23
+ {
24
+ "query": "MATCH (:IpRange{id: '0.0.0.0/0'})-[:MEMBER_OF_IP_RULE]->(:IpPermissionInbound)-[:MEMBER_OF_EC2_SECURITY_GROUP]->(group:EC2SecurityGroup)<-[:MEMBER_OF_EC2_SECURITY_GROUP|NETWORK_INTERFACE*..2]-(instance:EC2Instance) WITH instance WHERE (instance.publicipaddress IS NOT NULL) AND (instance.exposed_internet_type IS NULL OR NOT 'direct' IN instance.exposed_internet_type) SET instance.exposed_internet = true, instance.exposed_internet_type = CASE WHEN instance.exposed_internet_type IS NULL THEN ['direct'] WHEN NOT 'direct' IN instance.exposed_internet_type THEN instance.exposed_internet_type + ['direct'] ELSE instance.exposed_internet_type END;",
10
25
  "iterative": false
11
26
  },
12
27
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "statements": [
3
3
  {
4
- "query": "MATCH (n) where n.exposed_internet IS NOT NULL AND labels(n) IN ['GCPInstance'] WITH n LIMIT $LIMIT_SIZE REMOVE n.exposed_internet, n.exposed_internet_type return COUNT(*) as TotalCompleted",
4
+ "query": "MATCH (n:GCPInstance) where n.exposed_internet IS NOT NULL WITH n LIMIT $LIMIT_SIZE REMOVE n.exposed_internet, n.exposed_internet_type",
5
5
  "iterative": true,
6
6
  "iterationsize": 1000,
7
7
  "__comment__": "Delete exposed_internet off nodes so we can start fresh"
@@ -16,7 +16,17 @@ def build_cleanup_queries(node_schema: CartographyNodeSchema) -> List[str]:
16
16
  """
17
17
  Generates queries to clean up stale nodes and relationships from the given CartographyNodeSchema.
18
18
  Note that auto-cleanups for a node with no relationships is not currently supported.
19
+
19
20
  Algorithm:
21
+ 1. If node_schema has no relationships at all, return empty.
22
+
23
+ Otherwise,
24
+
25
+ 1. If node_schema doesn't have a sub_resource relationship, generate queries only to clean up its other
26
+ relationships. No nodes will be cleaned up.
27
+
28
+ Otherwise,
29
+
20
30
  1. First delete all stale nodes attached to the node_schema's sub resource
21
31
  2. Delete all stale node to sub resource relationships
22
32
  - We don't expect this to be very common (never for AWS resources, at least), but in case it is possible for an
@@ -25,11 +35,16 @@ def build_cleanup_queries(node_schema: CartographyNodeSchema) -> List[str]:
25
35
  :param node_schema: The given CartographyNodeSchema
26
36
  :return: A list of Neo4j queries to clean up nodes and relationships.
27
37
  """
38
+ if not node_schema.sub_resource_relationship and not node_schema.other_relationships:
39
+ return []
40
+
28
41
  if not node_schema.sub_resource_relationship:
29
- raise ValueError(
30
- "Auto-creating a cleanup job for a node_schema without a sub resource relationship is not supported. "
31
- f'Please check the class definition of "{node_schema.__class__.__name__}".',
32
- )
42
+ queries = []
43
+ other_rels = node_schema.other_relationships.rels if node_schema.other_relationships else []
44
+ for rel in other_rels:
45
+ query = _build_cleanup_rel_query_no_sub_resource(node_schema, rel)
46
+ queries.append(query)
47
+ return queries
33
48
 
34
49
  result = _build_cleanup_node_and_rel_queries(node_schema, node_schema.sub_resource_relationship)
35
50
  if node_schema.other_relationships:
@@ -41,6 +56,34 @@ def build_cleanup_queries(node_schema: CartographyNodeSchema) -> List[str]:
41
56
  return result
42
57
 
43
58
 
59
+ def _build_cleanup_rel_query_no_sub_resource(
60
+ node_schema: CartographyNodeSchema,
61
+ selected_relationship: CartographyRelSchema,
62
+ ) -> str:
63
+ """
64
+ Helper function to delete stale relationships for node_schemas that have no sub resource relationship defined.
65
+ """
66
+ if node_schema.sub_resource_relationship:
67
+ raise ValueError(
68
+ f'Expected {node_schema.label} to not exist. '
69
+ 'This function is intended for node_schemas without sub_resource_relationships.',
70
+ )
71
+ # Ensure the node is attached to the sub resource and delete the node
72
+ query_template = Template(
73
+ """
74
+ MATCH (n:$node_label)
75
+ $selected_rel_clause
76
+ WHERE r.lastupdated <> $UPDATE_TAG
77
+ WITH r LIMIT $LIMIT_SIZE
78
+ DELETE r;
79
+ """,
80
+ )
81
+ return query_template.safe_substitute(
82
+ node_label=node_schema.label,
83
+ selected_rel_clause=_build_selected_rel_clause(selected_relationship),
84
+ )
85
+
86
+
44
87
  def _build_cleanup_node_and_rel_queries(
45
88
  node_schema: CartographyNodeSchema,
46
89
  selected_relationship: CartographyRelSchema,
@@ -13,7 +13,7 @@ from cartography.graph.job import GraphJob
13
13
  from cartography.intel.aws.ec2.util import get_botocore_config
14
14
  from cartography.models.aws.ec2.auto_scaling_groups import EC2InstanceAutoScalingGroupSchema
15
15
  from cartography.models.aws.ec2.instances import EC2InstanceSchema
16
- from cartography.models.aws.ec2.keypairs import EC2KeyPairSchema
16
+ from cartography.models.aws.ec2.keypair_instance import EC2KeyPairInstanceSchema
17
17
  from cartography.models.aws.ec2.networkinterface_instance import EC2NetworkInterfaceInstanceSchema
18
18
  from cartography.models.aws.ec2.reservations import EC2ReservationSchema
19
19
  from cartography.models.aws.ec2.securitygroup_instance import EC2SecurityGroupInstanceSchema
@@ -193,16 +193,17 @@ def load_ec2_subnets(
193
193
 
194
194
 
195
195
  @timeit
196
- def load_ec2_key_pairs(
196
+ def load_ec2_keypair_instances(
197
197
  neo4j_session: neo4j.Session,
198
198
  key_pair_list: List[Dict[str, Any]],
199
199
  region: str,
200
200
  current_aws_account_id: str,
201
201
  update_tag: int,
202
202
  ) -> None:
203
+ # Load EC2 keypairs as known by describe-instances.
203
204
  load(
204
205
  neo4j_session,
205
- EC2KeyPairSchema(),
206
+ EC2KeyPairInstanceSchema(),
206
207
  key_pair_list,
207
208
  Region=region,
208
209
  AWS_ID=current_aws_account_id,
@@ -299,7 +300,7 @@ def load_ec2_instance_data(
299
300
  load_ec2_instance_nodes(neo4j_session, instance_list, region, current_aws_account_id, update_tag)
300
301
  load_ec2_subnets(neo4j_session, subnet_list, region, current_aws_account_id, update_tag)
301
302
  load_ec2_security_groups(neo4j_session, sg_list, region, current_aws_account_id, update_tag)
302
- load_ec2_key_pairs(neo4j_session, key_pair_list, region, current_aws_account_id, update_tag)
303
+ load_ec2_keypair_instances(neo4j_session, key_pair_list, region, current_aws_account_id, update_tag)
303
304
  load_ec2_network_interfaces(neo4j_session, nic_list, region, current_aws_account_id, update_tag)
304
305
  load_ec2_instance_ebs_volumes(neo4j_session, ebs_volumes_list, region, current_aws_account_id, update_tag)
305
306
 
@@ -1,13 +1,14 @@
1
1
  import logging
2
+ from typing import Any
2
3
  from typing import Dict
3
- from typing import List
4
4
 
5
5
  import boto3
6
6
  import neo4j
7
7
 
8
- from .util import get_botocore_config
8
+ from cartography.client.core.tx import load
9
9
  from cartography.graph.job import GraphJob
10
- from cartography.models.aws.ec2.keypairs import EC2KeyPairSchema
10
+ from cartography.intel.aws.ec2.util import get_botocore_config
11
+ from cartography.models.aws.ec2.keypair import EC2KeyPairSchema
11
12
  from cartography.util import aws_handle_regions
12
13
  from cartography.util import timeit
13
14
 
@@ -16,42 +17,45 @@ logger = logging.getLogger(__name__)
16
17
 
17
18
  @timeit
18
19
  @aws_handle_regions
19
- def get_ec2_key_pairs(boto3_session: boto3.session.Session, region: str) -> List[Dict]:
20
+ def get_ec2_key_pairs(boto3_session: boto3.session.Session, region: str) -> list[dict[str, Any]]:
20
21
  client = boto3_session.client('ec2', region_name=region, config=get_botocore_config())
21
22
  return client.describe_key_pairs()['KeyPairs']
22
23
 
23
24
 
25
+ def transform_ec2_key_pairs(
26
+ key_pairs: list[dict[str, Any]],
27
+ region: str,
28
+ current_aws_account_id: str,
29
+ ) -> list[dict[str, Any]]:
30
+ transformed_key_pairs = []
31
+ for key_pair in key_pairs:
32
+ key_name = key_pair["KeyName"]
33
+ transformed_key_pairs.append({
34
+ 'KeyPairArn': f'arn:aws:ec2:{region}:{current_aws_account_id}:key-pair/{key_name}',
35
+ 'KeyName': key_name,
36
+ 'KeyFingerprint': key_pair.get("KeyFingerprint"),
37
+ })
38
+ return transformed_key_pairs
39
+
40
+
24
41
  @timeit
25
42
  def load_ec2_key_pairs(
26
- neo4j_session: neo4j.Session, data: List[Dict], region: str, current_aws_account_id: str,
27
- update_tag: int,
43
+ neo4j_session: neo4j.Session,
44
+ data: list[dict[str, Any]],
45
+ region: str,
46
+ current_aws_account_id: str,
47
+ update_tag: int,
28
48
  ) -> None:
29
- ingest_key_pair = """
30
- MERGE (keypair:KeyPair:EC2KeyPair{arn: $ARN, id: $ARN})
31
- ON CREATE SET keypair.firstseen = timestamp()
32
- SET keypair.keyname = $KeyName, keypair.keyfingerprint = $KeyFingerprint, keypair.region = $Region,
33
- keypair.lastupdated = $update_tag
34
- WITH keypair
35
- MATCH (aa:AWSAccount{id: $AWS_ACCOUNT_ID})
36
- MERGE (aa)-[r:RESOURCE]->(keypair)
37
- ON CREATE SET r.firstseen = timestamp()
38
- SET r.lastupdated = $update_tag
39
- """
40
-
41
- for key_pair in data:
42
- key_name = key_pair["KeyName"]
43
- key_fingerprint = key_pair.get("KeyFingerprint")
44
- key_pair_arn = f'arn:aws:ec2:{region}:{current_aws_account_id}:key-pair/{key_name}'
45
-
46
- neo4j_session.run(
47
- ingest_key_pair,
48
- ARN=key_pair_arn,
49
- KeyName=key_name,
50
- KeyFingerprint=key_fingerprint,
51
- AWS_ACCOUNT_ID=current_aws_account_id,
52
- Region=region,
53
- update_tag=update_tag,
54
- )
49
+ # Load EC2 keypairs as known by describe-key-pairs
50
+ logger.info(f"Loading {len(data)} EC2 keypairs for region '{region}' into graph.")
51
+ load(
52
+ neo4j_session,
53
+ EC2KeyPairSchema(),
54
+ data,
55
+ Region=region,
56
+ AWS_ID=current_aws_account_id,
57
+ lastupdated=update_tag,
58
+ )
55
59
 
56
60
 
57
61
  @timeit
@@ -61,11 +65,16 @@ def cleanup_ec2_key_pairs(neo4j_session: neo4j.Session, common_job_parameters: D
61
65
 
62
66
  @timeit
63
67
  def sync_ec2_key_pairs(
64
- neo4j_session: neo4j.Session, boto3_session: boto3.session.Session, regions: List[str], current_aws_account_id: str,
65
- update_tag: int, common_job_parameters: Dict,
68
+ neo4j_session: neo4j.Session,
69
+ boto3_session: boto3.session.Session,
70
+ regions: list[str],
71
+ current_aws_account_id: str,
72
+ update_tag: int,
73
+ common_job_parameters: dict[str, Any],
66
74
  ) -> None:
67
75
  for region in regions:
68
76
  logger.info("Syncing EC2 key pairs for region '%s' in account '%s'.", region, current_aws_account_id)
69
77
  data = get_ec2_key_pairs(boto3_session, region)
70
- load_ec2_key_pairs(neo4j_session, data, region, current_aws_account_id, update_tag)
78
+ transformed_data = transform_ec2_key_pairs(data, region, current_aws_account_id)
79
+ load_ec2_key_pairs(neo4j_session, transformed_data, region, current_aws_account_id, update_tag)
71
80
  cleanup_ec2_key_pairs(neo4j_session, common_job_parameters)
@@ -82,26 +82,6 @@ def get_permission_sets(boto3_session: boto3.session.Session, instance_arn: str,
82
82
  return permission_sets
83
83
 
84
84
 
85
- @timeit
86
- def get_permission_set_roles(
87
- boto3_session: boto3.session.Session,
88
- instance_arn: str,
89
- permission_set_arn: str,
90
- region: str,
91
- ) -> List[Dict]:
92
- """
93
- Get all accounts associated with a given permission set
94
- """
95
- client = boto3_session.client('sso-admin', region_name=region)
96
- accounts = []
97
-
98
- paginator = client.get_paginator('list_accounts_for_provisioned_permission_set')
99
- for page in paginator.paginate(InstanceArn=instance_arn, PermissionSetArn=permission_set_arn):
100
- accounts.extend(page.get('AccountIds', []))
101
-
102
- return accounts
103
-
104
-
105
85
  @timeit
106
86
  def load_permission_sets(
107
87
  neo4j_session: neo4j.Session,
@@ -128,6 +108,7 @@ def load_permission_sets(
128
108
 
129
109
 
130
110
  @timeit
111
+ @aws_handle_regions
131
112
  def get_sso_users(
132
113
  boto3_session: boto3.session.Session,
133
114
  identity_store_id: str,
@@ -176,6 +157,7 @@ def load_sso_users(
176
157
 
177
158
 
178
159
  @timeit
160
+ @aws_handle_regions
179
161
  def get_role_assignments(
180
162
  boto3_session: boto3.session.Session,
181
163
  users: List[Dict],
@@ -231,6 +213,7 @@ def load_role_assignments(
231
213
  )
232
214
 
233
215
 
216
+ @timeit
234
217
  def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]) -> None:
235
218
  GraphJob.from_node_schema(AWSIdentityCenterInstanceSchema(), common_job_parameters).run(neo4j_session)
236
219
  GraphJob.from_node_schema(AWSPermissionSetSchema(), common_job_parameters).run(neo4j_session)
@@ -8,13 +8,13 @@ from typing import Tuple
8
8
  import neo4j
9
9
 
10
10
  from cartography.client.core.tx import load
11
+ from cartography.graph.job import GraphJob
11
12
  from cartography.intel.github.util import fetch_all
12
13
  from cartography.models.github.orgs import GitHubOrganizationSchema
13
14
  from cartography.models.github.users import GitHubOrganizationUserSchema
14
15
  from cartography.models.github.users import GitHubUnaffiliatedUserSchema
15
16
  from cartography.stats import get_stats_client
16
17
  from cartography.util import merge_module_sync_metadata
17
- from cartography.util import run_cleanup_job
18
18
  from cartography.util import timeit
19
19
 
20
20
  logger = logging.getLogger(__name__)
@@ -210,6 +210,13 @@ def load_organization(
210
210
  )
211
211
 
212
212
 
213
+ @timeit
214
+ def cleanup(neo4j_session: neo4j.Session, common_job_parameters: dict[str, Any]) -> None:
215
+ logger.info("Cleaning up GitHub users")
216
+ GraphJob.from_node_schema(GitHubOrganizationUserSchema(), common_job_parameters).run(neo4j_session)
217
+ GraphJob.from_node_schema(GitHubUnaffiliatedUserSchema(), common_job_parameters).run(neo4j_session)
218
+
219
+
213
220
  @timeit
214
221
  def sync(
215
222
  neo4j_session: neo4j.Session,
@@ -236,8 +243,8 @@ def sync(
236
243
  neo4j_session, GitHubUnaffiliatedUserSchema(), processed_unaffiliated_user_data, org_data,
237
244
  common_job_parameters['UPDATE_TAG'],
238
245
  )
239
- # no automated cleanup job for users because user node has no sub_resource_relationship
240
- run_cleanup_job('github_org_and_users_cleanup.json', neo4j_session, common_job_parameters)
246
+ cleanup(neo4j_session, common_job_parameters)
247
+
241
248
  merge_module_sync_metadata(
242
249
  neo4j_session,
243
250
  group_type='GitHubOrganization',
@@ -3,19 +3,23 @@ from dataclasses import dataclass
3
3
  from cartography.models.core.common import PropertyRef
4
4
  from cartography.models.core.nodes import CartographyNodeProperties
5
5
  from cartography.models.core.nodes import CartographyNodeSchema
6
+ from cartography.models.core.nodes import ExtraNodeLabels
6
7
  from cartography.models.core.relationships import CartographyRelProperties
7
8
  from cartography.models.core.relationships import CartographyRelSchema
8
9
  from cartography.models.core.relationships import LinkDirection
9
10
  from cartography.models.core.relationships import make_target_node_matcher
10
- from cartography.models.core.relationships import OtherRelationships
11
11
  from cartography.models.core.relationships import TargetNodeMatcher
12
12
 
13
13
 
14
14
  @dataclass(frozen=True)
15
15
  class EC2KeyPairNodeProperties(CartographyNodeProperties):
16
+ """
17
+ Properties for EC2 keypairs from describe-key-pairs
18
+ """
16
19
  id: PropertyRef = PropertyRef('KeyPairArn')
17
20
  arn: PropertyRef = PropertyRef('KeyPairArn', extra_index=True)
18
21
  keyname: PropertyRef = PropertyRef('KeyName')
22
+ keyfingerprint: PropertyRef = PropertyRef('KeyFingerprint')
19
23
  region: PropertyRef = PropertyRef('Region', set_in_kwargs=True)
20
24
  lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
21
25
 
@@ -27,38 +31,24 @@ class EC2KeyPairToAwsAccountRelProperties(CartographyRelProperties):
27
31
 
28
32
  @dataclass(frozen=True)
29
33
  class EC2KeyPairToAWSAccount(CartographyRelSchema):
34
+ """
35
+ Relationship schema for EC2 keypairs to AWS Accounts
36
+ """
30
37
  target_node_label: str = 'AWSAccount'
31
38
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
32
39
  {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
33
40
  )
34
41
  direction: LinkDirection = LinkDirection.INWARD
35
- rel_label: str = "RESOURCE"
42
+ rel_label: str = 'RESOURCE'
36
43
  properties: EC2KeyPairToAwsAccountRelProperties = EC2KeyPairToAwsAccountRelProperties()
37
44
 
38
45
 
39
- @dataclass(frozen=True)
40
- class EC2KeyPairToEC2InstanceRelProperties(CartographyRelProperties):
41
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
42
-
43
-
44
- @dataclass(frozen=True)
45
- class EC2KeyPairToEC2Instance(CartographyRelSchema):
46
- target_node_label: str = 'EC2Instance'
47
- target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
48
- {'id': PropertyRef('InstanceId')},
49
- )
50
- direction: LinkDirection = LinkDirection.OUTWARD
51
- rel_label: str = "SSH_LOGIN_TO"
52
- properties: EC2KeyPairToEC2InstanceRelProperties = EC2KeyPairToEC2InstanceRelProperties()
53
-
54
-
55
46
  @dataclass(frozen=True)
56
47
  class EC2KeyPairSchema(CartographyNodeSchema):
48
+ """
49
+ Schema for EC2 keypairs from describe-key-pairs
50
+ """
57
51
  label: str = 'EC2KeyPair'
52
+ extra_node_labels: ExtraNodeLabels = ExtraNodeLabels(['KeyPair'])
58
53
  properties: EC2KeyPairNodeProperties = EC2KeyPairNodeProperties()
59
54
  sub_resource_relationship: EC2KeyPairToAWSAccount = EC2KeyPairToAWSAccount()
60
- other_relationships: OtherRelationships = OtherRelationships(
61
- [
62
- EC2KeyPairToEC2Instance(),
63
- ],
64
- )
@@ -0,0 +1,69 @@
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.nodes import ExtraNodeLabels
7
+ from cartography.models.core.relationships import CartographyRelProperties
8
+ from cartography.models.core.relationships import CartographyRelSchema
9
+ from cartography.models.core.relationships import LinkDirection
10
+ from cartography.models.core.relationships import make_target_node_matcher
11
+ from cartography.models.core.relationships import OtherRelationships
12
+ from cartography.models.core.relationships import TargetNodeMatcher
13
+
14
+
15
+ @dataclass(frozen=True)
16
+ class EC2KeyPairInstanceNodeProperties(CartographyNodeProperties):
17
+ id: PropertyRef = PropertyRef('KeyPairArn')
18
+ arn: PropertyRef = PropertyRef('KeyPairArn', extra_index=True)
19
+ keyname: PropertyRef = PropertyRef('KeyName')
20
+ region: PropertyRef = PropertyRef('Region', set_in_kwargs=True)
21
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
22
+
23
+
24
+ @dataclass(frozen=True)
25
+ class EC2KeyPairInstanceToAwsAccountRelProperties(CartographyRelProperties):
26
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
27
+
28
+
29
+ @dataclass(frozen=True)
30
+ class EC2KeyPairInstanceToAWSAccount(CartographyRelSchema):
31
+ target_node_label: str = 'AWSAccount'
32
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
33
+ {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
34
+ )
35
+ direction: LinkDirection = LinkDirection.INWARD
36
+ rel_label: str = "RESOURCE"
37
+ properties: EC2KeyPairInstanceToAwsAccountRelProperties = EC2KeyPairInstanceToAwsAccountRelProperties()
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class EC2KeyPairInstanceToEC2InstanceRelProperties(CartographyRelProperties):
42
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
43
+
44
+
45
+ @dataclass(frozen=True)
46
+ class EC2KeyPairInstanceToEC2Instance(CartographyRelSchema):
47
+ target_node_label: str = 'EC2Instance'
48
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
49
+ {'id': PropertyRef('InstanceId')},
50
+ )
51
+ direction: LinkDirection = LinkDirection.OUTWARD
52
+ rel_label: str = "SSH_LOGIN_TO"
53
+ properties: EC2KeyPairInstanceToEC2InstanceRelProperties = EC2KeyPairInstanceToEC2InstanceRelProperties()
54
+
55
+
56
+ @dataclass(frozen=True)
57
+ class EC2KeyPairInstanceSchema(CartographyNodeSchema):
58
+ """
59
+ EC2 keypairs as known by describe-instances.
60
+ """
61
+ label: str = 'EC2KeyPair'
62
+ extra_node_labels: ExtraNodeLabels = ExtraNodeLabels(['KeyPair'])
63
+ properties: EC2KeyPairInstanceNodeProperties = EC2KeyPairInstanceNodeProperties()
64
+ sub_resource_relationship: EC2KeyPairInstanceToAWSAccount = EC2KeyPairInstanceToAWSAccount()
65
+ other_relationships: OtherRelationships = OtherRelationships(
66
+ [
67
+ EC2KeyPairInstanceToEC2Instance(),
68
+ ],
69
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cartography
3
- Version: 0.97.0
3
+ Version: 0.98.0rc1
4
4
  Summary: Explore assets and their relationships across your technical infrastructure.
5
5
  Home-page: https://www.github.com/cartography-cncf/cartography
6
6
  Maintainer: Cartography Contributors
@@ -12,11 +12,11 @@ cartography/client/aws/iam.py,sha256=dYsGikc36DEsSeR2XVOVFFUDwuU9yWj_EVkpgVYCFgM
12
12
  cartography/client/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  cartography/client/core/tx.py,sha256=FcUPfmNIKSXkN5UK3nL5-GFoGkPYXmAxIWP7knvrHWg,10794
14
14
  cartography/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- cartography/data/indexes.cypher,sha256=zMEzytgcvMLgclMmCkFUdWp4t_EFsOEOp1M2v1vGctM,27208
15
+ cartography/data/indexes.cypher,sha256=KMhj8DoKl3d-o6Zx4PY6IZ_8eZNPqZWWVNnOzIi5dRw,26946
16
16
  cartography/data/permission_relationships.yaml,sha256=RuKGGc_3ZUQ7ag0MssB8k_zaonCkVM5E8I_svBWTmGc,969
17
17
  cartography/data/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  cartography/data/jobs/analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- cartography/data/jobs/analysis/aws_ec2_asset_exposure.json,sha256=PRM7TJwO3gLkGtez-hg5v5avDkuAcF-bQQCK6stecLg,2726
19
+ cartography/data/jobs/analysis/aws_ec2_asset_exposure.json,sha256=wSR_-0TbieAMSFOWpNZohgbDHooa-F6jHm8DxdntLOY,3397
20
20
  cartography/data/jobs/analysis/aws_ec2_iaminstance.json,sha256=98wfe8pjwS-iQIjUpM1rxuASdxk7BGl9ooigrwfpmvU,500
21
21
  cartography/data/jobs/analysis/aws_ec2_iaminstanceprofile.json,sha256=7M8k0p0SvSYVzCk358FnUQ865IX25TyumtHTXqZS-t8,526
22
22
  cartography/data/jobs/analysis/aws_ec2_keypair_analysis.json,sha256=_ZBczunZbx5NHAbfVc4v6vJsbyl1xaePLzj4cyxW-4A,1741
@@ -24,7 +24,7 @@ cartography/data/jobs/analysis/aws_eks_asset_exposure.json,sha256=Z6z4YTNJJqUJl2
24
24
  cartography/data/jobs/analysis/aws_foreign_accounts.json,sha256=b8Li_KQLwIvNXxWt0F1bVTV1Vg9dxsbr7ZE8LH2-woc,686
25
25
  cartography/data/jobs/analysis/aws_lambda_ecr.json,sha256=wM10Gn0HoNP-sOj3S_Sjqh4mLsh-f2QkonkFuOohs_U,641
26
26
  cartography/data/jobs/analysis/aws_s3acl_analysis.json,sha256=ihTzHXAjpulNo0F1swZlZtxqKsZwtt2QXoB7yaX6gKA,2737
27
- cartography/data/jobs/analysis/gcp_compute_asset_inet_exposure.json,sha256=lIurpVOAHZ3u_pfpRhcC5zprxXKqOWG4miGIkMeCfcE,4695
27
+ cartography/data/jobs/analysis/gcp_compute_asset_inet_exposure.json,sha256=lXuxrcHLom_DvsDvCQjZsqwRLMkwtKtjj6CRmo0eweI,4640
28
28
  cartography/data/jobs/analysis/gcp_gke_asset_exposure.json,sha256=7SJc9TeeIWFMDmHOWgmjgaIzjmCClLjJTPS4bGlaEF0,643
29
29
  cartography/data/jobs/analysis/gcp_gke_basic_auth.json,sha256=qLkrw1eZvV9ETtkIQN3v9hXnYN3ujAMyfIpqUj5YGo8,681
30
30
  cartography/data/jobs/analysis/gsuite_human_link.json,sha256=ArWA51fNIeeXwYiroJbKnuqN8y-TLrndOq0ZdC9q5os,541
@@ -102,7 +102,6 @@ cartography/data/jobs/cleanup/gcp_crm_project_cleanup.json,sha256=JImcuuz9HI2TL0
102
102
  cartography/data/jobs/cleanup/gcp_dns_cleanup.json,sha256=NGs5UYFmm65Rq8gyqbzIe8_OnFchfpNFf9iAcIj_hyY,1286
103
103
  cartography/data/jobs/cleanup/gcp_gke_cluster_cleanup.json,sha256=3bMEJ44AEvjkj_1ibclk6Ys5r1LniUWefpZ_U5hTwHI,671
104
104
  cartography/data/jobs/cleanup/gcp_storage_bucket_cleanup.json,sha256=sGygB_meoCpGdGgEZtIlC4L-19meAXdfP99gkNJHD7o,1288
105
- cartography/data/jobs/cleanup/github_org_and_users_cleanup.json,sha256=vjaOlWdnjaCHmvmaWadOzHXqFnjpR1wW8cykb_M54fM,1010
106
105
  cartography/data/jobs/cleanup/github_repos_cleanup.json,sha256=Ko6zya72yLjLt_m-wogAUmuzzL2-IJiO457clEHFxPk,3676
107
106
  cartography/data/jobs/cleanup/gsuite_ingest_groups_cleanup.json,sha256=ddXAUi6aVi2htf5R1bNn6YrC3SjshjLBgWtlzBgZ9Do,961
108
107
  cartography/data/jobs/cleanup/gsuite_ingest_users_cleanup.json,sha256=0qMLbVSTyq5F9vt4-TvVa3YAAvZCpPtzF9EwblaTxWg,353
@@ -133,7 +132,7 @@ cartography/driftdetect/shortcut.py,sha256=0AvX9vZGNRWeLiRqxU7eOOo77gcfufHx4IHZv
133
132
  cartography/driftdetect/storage.py,sha256=6ziscwJh34_1ylrSAK6B-U6o09xDhIa7Yb-V1kisveQ,1549
134
133
  cartography/driftdetect/util.py,sha256=Lqxv8QoFn3_3Fz18qCOjkjJ6yBwgrHjrxXmArBAEdkc,929
135
134
  cartography/graph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
136
- cartography/graph/cleanupbuilder.py,sha256=87vFrOJo66hOrrqeNwXp18WrNQEheHTlZko9KUkXWhY,8021
135
+ cartography/graph/cleanupbuilder.py,sha256=zZc7SvRz23sU_VN-RrHoyhug7dRZlqbbLwHbrlPdVik,9411
137
136
  cartography/graph/context.py,sha256=RGxGb8EnxowcqjR0nFF86baNhgRHeUF9wjIoFUoG8LU,1230
138
137
  cartography/graph/job.py,sha256=RZWsbNhHuJlcSpw4C73ZuovRTp7kGrcm3X9yUH8vT1Q,7488
139
138
  cartography/graph/querybuilder.py,sha256=7DtIGPlfeKcIWKw_ReCAX1OeUkhSnIRV_reeVaKL6I4,20416
@@ -153,7 +152,7 @@ cartography/intel/aws/elasticache.py,sha256=fCI47aDFmIDyE26GiReKYb6XIZUwrzcvsXBQ
153
152
  cartography/intel/aws/elasticsearch.py,sha256=ZL7MkXF_bXRSoXuDSI1dwGckRLG2zDB8LuAD07vSLnE,8374
154
153
  cartography/intel/aws/emr.py,sha256=xhWBVZngxJRFjMEDxwq3G6SgytRGLq0v2a_CeDvByR0,3372
155
154
  cartography/intel/aws/iam.py,sha256=zRlF9cKcYm44iL63G6bd-_flNOFHVrjsEfW0jZHpUNg,32387
156
- cartography/intel/aws/identitycenter.py,sha256=Mgd7ZNj8W7IghVSXovgYyQDwRt_MjxrBPGyDKxlFsoQ,9495
155
+ cartography/intel/aws/identitycenter.py,sha256=OnyvsSfn6AszB2e9dPAsGmzgne0zq0_7Ta0A6k_l_TE,8956
157
156
  cartography/intel/aws/inspector.py,sha256=S22ZgRKEnmnBTJ-u0rodqRPB7_LkSIek47NeBxN4XJw,9336
158
157
  cartography/intel/aws/kms.py,sha256=bZUzMxAH_DsAcGTJBs08gg2tLKYu-QWjvMvV9C-6v50,11731
159
158
  cartography/intel/aws/lambda_function.py,sha256=KKTyn53xpaMI9WvIqxmsOASFwflHt-2_5ow-zUFc2wg,9890
@@ -173,9 +172,9 @@ cartography/intel/aws/ec2/__init__.py,sha256=IDK2Yap7mllK_ab6yVMLXatJ94znIkn-szv
173
172
  cartography/intel/aws/ec2/auto_scaling_groups.py,sha256=ylfks8_oC0-fVMnToFbmRcbKdEN0H17LlN1-ZqW6ULc,8148
174
173
  cartography/intel/aws/ec2/elastic_ip_addresses.py,sha256=0k4NwS73VyWbEj5jXvSkaq2RNvmAlBlrN-UKa_Bj0uk,3957
175
174
  cartography/intel/aws/ec2/images.py,sha256=heElwHJGqVD3iUJjxwA_Sdc3CmE4HPs00CTMHuQ1wkc,3782
176
- cartography/intel/aws/ec2/instances.py,sha256=IJS9TJhk0aqFaRbmUOCE_sHVhZJLg8fPTF8zEnTlyvk,12372
175
+ cartography/intel/aws/ec2/instances.py,sha256=uI8eVJmeEybS8y_T8CVKAkwxJyVDCH7sbuEJYeWGSWY,12468
177
176
  cartography/intel/aws/ec2/internet_gateways.py,sha256=dI-4-85_3DGGZZBcY_DN6XqESx9P26S6jKok314lcnQ,2883
178
- cartography/intel/aws/ec2/key_pairs.py,sha256=SvRgd56vE4eouvTSNoFK8PP8HYoECO91goxc36oq_FY,2508
177
+ cartography/intel/aws/ec2/key_pairs.py,sha256=g4imIo_5jk8upq9J4--erg-OZXG2i3cJMe6SnNCYj9s,2635
179
178
  cartography/intel/aws/ec2/launch_templates.py,sha256=aeqaL8On38ET8nM8bISsIXLy6PkZoV-tqSWG38YXgkI,6010
180
179
  cartography/intel/aws/ec2/load_balancer_v2s.py,sha256=95FfQQn740gexINIHDJizOM4OKzRtQT_y2XQMipQ5Dg,8661
181
180
  cartography/intel/aws/ec2/load_balancers.py,sha256=1GwErzGqi3BKCARqfGJcD_r_D84rFKVy5kNMas9jAok,6756
@@ -231,7 +230,7 @@ cartography/intel/gcp/storage.py,sha256=oO_ayEhkXlj2Gn7T5MU41ZXiqwRwe6Ud4wzqyRTs
231
230
  cartography/intel/github/__init__.py,sha256=y876JJGTDJZEOFCDiNCJfcLNxN24pVj4s2N0YmuuoaE,1914
232
231
  cartography/intel/github/repos.py,sha256=MmpxZASDJFQxDeSMxX3pZcpxCHFPos4_uYC_cX9KjOg,29865
233
232
  cartography/intel/github/teams.py,sha256=AltQSmBHHmyzBtnRkez9Bo5yChEKBSt3wwzhGcfqmX4,14180
234
- cartography/intel/github/users.py,sha256=f_YIDwdNECRg7wRwY8qZ5mztm7m3SIgOz8BbfveRzy8,8734
233
+ cartography/intel/github/users.py,sha256=MCLE0V0UCzQm3k3KmrNe6PYkI6usRQZYy2rCN3mT8o0,8948
235
234
  cartography/intel/github/util.py,sha256=K0cXOPuhnGvN-aqcSUBO3vTuKQLjufVal9kn2HwOpbo,8110
236
235
  cartography/intel/gsuite/__init__.py,sha256=AGIUskGlLCVGHbnQicNpNWi9AvmV7_7hUKTt-hsB2J8,4306
237
236
  cartography/intel/gsuite/api.py,sha256=J0dkNdfBVMrEv8vvStQu7YKVxXSyV45WueFhUS4aOG4,10310
@@ -288,7 +287,8 @@ cartography/models/aws/ec2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
288
287
  cartography/models/aws/ec2/auto_scaling_groups.py,sha256=ImIu-i5iU_CJQ25oa2MDnOhOjL4jcpBagPiB95JUvSE,8660
289
288
  cartography/models/aws/ec2/images.py,sha256=uGhXS7Xb6sKUdwwkS0O0dWP4sIREjusUaV_unODv9gE,3012
290
289
  cartography/models/aws/ec2/instances.py,sha256=cNMHngdGNRhxoyID6AmG2F7CQGC1fYani8DV8lSKvsI,3902
291
- cartography/models/aws/ec2/keypairs.py,sha256=scKC3SdExHAWkPNmb6tT9LK-9q4sweqS2ejFzMec10M,2630
290
+ cartography/models/aws/ec2/keypair.py,sha256=UzKj1-Oyd-xMAJeuELzkGlDNAih1H9KpBwEgCCp54T8,2235
291
+ cartography/models/aws/ec2/keypair_instance.py,sha256=M1Ru8Z_2izW0cADAnQVVHaKsT_4FucNZnjr2DIGncJY,2943
292
292
  cartography/models/aws/ec2/launch_configurations.py,sha256=zdfWJEx93HXDXd_IzSEkhvcztkJI7_v_TCE_d8ZNAyI,2764
293
293
  cartography/models/aws/ec2/launch_template_versions.py,sha256=RitfnAuAj0XpFsCXkRbtUhHMAi8Vsvmtury231eKvGU,3897
294
294
  cartography/models/aws/ec2/launch_templates.py,sha256=GqiwFuMp72LNSt2eQlp2WfdU_vHsom-xKV5AaUewSHQ,2157
@@ -353,9 +353,9 @@ cartography/models/snipeit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
353
353
  cartography/models/snipeit/asset.py,sha256=FyRAaeXuZjMy0eUQcSDFcgEAF5lbLMlvqp1Tv9d3Lv4,3238
354
354
  cartography/models/snipeit/tenant.py,sha256=p4rFnpNNuF1W5ilGBbexDaETWTwavfb38RcQGoImkQI,679
355
355
  cartography/models/snipeit/user.py,sha256=MsB4MiCVNTH6JpESime7cOkB89autZOXQpL6Z0l7L6o,2113
356
- cartography-0.97.0.dist-info/LICENSE,sha256=kvLEBRYaQ1RvUni6y7Ti9uHeooqnjPoo6n_-0JO1ETc,11351
357
- cartography-0.97.0.dist-info/METADATA,sha256=KXebB76HbcUfcT1umMgUjh0c8lw_ah1wCW1SEtZ5rWU,1938
358
- cartography-0.97.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
359
- cartography-0.97.0.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
360
- cartography-0.97.0.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
361
- cartography-0.97.0.dist-info/RECORD,,
356
+ cartography-0.98.0rc1.dist-info/LICENSE,sha256=kvLEBRYaQ1RvUni6y7Ti9uHeooqnjPoo6n_-0JO1ETc,11351
357
+ cartography-0.98.0rc1.dist-info/METADATA,sha256=u3q-XzntD_-Ds4au9jVOAbjB3y1SQfYjU3WrDTaY0fk,1941
358
+ cartography-0.98.0rc1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
359
+ cartography-0.98.0rc1.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
360
+ cartography-0.98.0rc1.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
361
+ cartography-0.98.0rc1.dist-info/RECORD,,
@@ -1,28 +0,0 @@
1
- {
2
- "statements": [{
3
- "query": "MATCH (n:GitHubUser) WHERE n.lastupdated <> $UPDATE_TAG WITH n LIMIT $LIMIT_SIZE DETACH DELETE (n)",
4
- "iterative": true,
5
- "iterationsize": 100
6
- },
7
- {
8
- "query": "MATCH (n:GitHubOrganization) WHERE n.lastupdated <> $UPDATE_TAG WITH n LIMIT $LIMIT_SIZE DETACH DELETE (n)",
9
- "iterative": true,
10
- "iterationsize": 100
11
- },
12
- {
13
- "query": "MATCH (:GitHubUser)-[r:OWNER]->(:GitHubRepository) WHERE r.lastupdated <> $UPDATE_TAG WITH r LIMIT $LIMIT_SIZE DELETE (r)",
14
- "iterative": true,
15
- "iterationsize": 100
16
- },
17
- {
18
- "query": "MATCH (:GitHubUser)-[r:MEMBER_OF]->(:GitHubOrganization) WHERE r.lastupdated <> $UPDATE_TAG WITH r LIMIT $LIMIT_SIZE DELETE (r)",
19
- "iterative": true,
20
- "iterationsize": 100
21
- },
22
- {
23
- "query": "MATCH (:GitHubUser)-[r:UNAFFILIATED]->(:GitHubOrganization) WHERE r.lastupdated <> $UPDATE_TAG WITH r LIMIT $LIMIT_SIZE DELETE (r)",
24
- "iterative": true,
25
- "iterationsize": 100
26
- }],
27
- "name": "cleanup GitHub users data"
28
- }