cartography 0.91.0__py3-none-any.whl → 0.92.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.

@@ -200,12 +200,6 @@ CREATE INDEX IF NOT EXISTS FOR (n:KMSGrant) ON (n.lastupdated);
200
200
  CREATE INDEX IF NOT EXISTS FOR (n:LaunchConfiguration) ON (n.id);
201
201
  CREATE INDEX IF NOT EXISTS FOR (n:LaunchConfiguration) ON (n.name);
202
202
  CREATE INDEX IF NOT EXISTS FOR (n:LaunchConfiguration) ON (n.lastupdated);
203
- CREATE INDEX IF NOT EXISTS FOR (n:LaunchTemplate) ON (n.id);
204
- CREATE INDEX IF NOT EXISTS FOR (n:LaunchTemplate) ON (n.name);
205
- CREATE INDEX IF NOT EXISTS FOR (n:LaunchTemplate) ON (n.lastupdated);
206
- CREATE INDEX IF NOT EXISTS FOR (n:LaunchTemplateVersion) ON (n.id);
207
- CREATE INDEX IF NOT EXISTS FOR (n:LaunchTemplateVersion) ON (n.name);
208
- CREATE INDEX IF NOT EXISTS FOR (n:LaunchTemplateVersion) ON (n.lastupdated);
209
203
  CREATE INDEX IF NOT EXISTS FOR (n:LoadBalancer) ON (n.dnsname);
210
204
  CREATE INDEX IF NOT EXISTS FOR (n:LoadBalancer) ON (n.id);
211
205
  CREATE INDEX IF NOT EXISTS FOR (n:LoadBalancer) ON (n.lastupdated);
@@ -1,13 +1,14 @@
1
1
  import logging
2
- from typing import Dict
3
- from typing import List
2
+ from typing import Any
4
3
 
5
4
  import boto3
6
5
  import neo4j
7
6
 
8
7
  from .util import get_botocore_config
8
+ from cartography.client.core.tx import load
9
+ from cartography.models.aws.ec2.launch_template_versions import LaunchTemplateVersionSchema
10
+ from cartography.models.aws.ec2.launch_templates import LaunchTemplateSchema
9
11
  from cartography.util import aws_handle_regions
10
- from cartography.util import run_cleanup_job
11
12
  from cartography.util import timeit
12
13
 
13
14
  logger = logging.getLogger(__name__)
@@ -15,101 +16,119 @@ logger = logging.getLogger(__name__)
15
16
 
16
17
  @timeit
17
18
  @aws_handle_regions
18
- def get_launch_templates(boto3_session: boto3.session.Session, region: str) -> List[Dict]:
19
+ def get_launch_templates(boto3_session: boto3.session.Session, region: str) -> list[dict[str, Any]]:
19
20
  client = boto3_session.client('ec2', region_name=region, config=get_botocore_config())
20
21
  paginator = client.get_paginator('describe_launch_templates')
21
- templates: List[Dict] = []
22
+ templates: list[dict[str, Any]] = []
22
23
  for page in paginator.paginate():
23
24
  templates.extend(page['LaunchTemplates'])
24
- for template in templates:
25
- template_versions: List[Dict] = []
26
- v_paginator = client.get_paginator('describe_launch_template_versions')
27
- for versions in v_paginator.paginate(LaunchTemplateId=template['LaunchTemplateId']):
28
- template_versions.extend(versions["LaunchTemplateVersions"])
29
- template["_template_versions"] = template_versions
30
25
  return templates
31
26
 
32
27
 
28
+ def transform_launch_templates(templates: list[dict[str, Any]]) -> list[dict[str, Any]]:
29
+ result: list[dict[str, Any]] = []
30
+ for template in templates:
31
+ current = template.copy()
32
+ current['CreateTime'] = str(int(current['CreateTime'].timestamp()))
33
+ result.append(current)
34
+ return result
35
+
36
+
33
37
  @timeit
34
38
  def load_launch_templates(
35
- neo4j_session: neo4j.Session, data: List[Dict], region: str, current_aws_account_id: str, update_tag: int,
39
+ neo4j_session: neo4j.Session,
40
+ data: list[dict[str, Any]],
41
+ region: str,
42
+ current_aws_account_id: str,
43
+ update_tag: int,
36
44
  ) -> None:
37
- ingest_lt = """
38
- UNWIND $launch_templates as lt
39
- MERGE (template:LaunchTemplate{id: lt.LaunchTemplateId})
40
- ON CREATE SET template.firstseen = timestamp(),
41
- template.name = lt.LaunchTemplateName,
42
- template.create_time = lt.CreateTime,
43
- template.created_by = lt.CreatedBy
44
- SET template.default_version_number = lt.DefaultVersionNumber,
45
- template.latest_version_number = lt.LatestVersionNumber,
46
- template.lastupdated = $update_tag,
47
- template.region=$Region
48
- WITH template, lt._template_versions as versions
49
- MATCH (aa:AWSAccount{id: $AWS_ACCOUNT_ID})
50
- MERGE (aa)-[r:RESOURCE]->(template)
51
- ON CREATE SET r.firstseen = timestamp()
52
- SET r.lastupdated = $update_tag
53
- WITH template, versions
54
- UNWIND versions as tv
55
- MERGE (version:LaunchTemplateVersion{id: tv.LaunchTemplateId + '-' + tv.VersionNumber})
56
- ON CREATE SET version.firstseen = timestamp(),
57
- version.name = tv.LaunchTemplateName,
58
- version.create_time = tv.CreateTime,
59
- version.created_by = tv.CreatedBy,
60
- version.default_version = tv.DefaultVersion,
61
- version.version_number = tv.VersionNumber,
62
- version.version_description = tv.VersionDescription,
63
- version.kernel_id = tv.LaunchTemplateData.KernelId,
64
- version.ebs_optimized = tv.LaunchTemplateData.EbsOptimized,
65
- version.iam_instance_profile_arn = tv.LaunchTemplateData.IamInstanceProfile.Arn,
66
- version.iam_instance_profile_name = tv.LaunchTemplateData.IamInstanceProfile.Name,
67
- version.image_id = tv.LaunchTemplateData.ImageId,
68
- version.instance_type = tv.LaunchTemplateData.InstanceType,
69
- version.key_name = tv.LaunchTemplateData.KeyName,
70
- version.monitoring_enabled = tv.LaunchTemplateData.Monitoring.Enabled,
71
- version.ramdisk_id = tv.LaunchTemplateData.RamdiskId,
72
- version.disable_api_termination = tv.LaunchTemplateData.DisableApiTermination,
73
- version.instance_initiated_shutdown_behavior = tv.LaunchTemplateData.InstanceInitiatedShutdownBehavior,
74
- version.security_group_ids = tv.LaunchTemplateData.SecurityGroupIds,
75
- version.security_groups = tv.LaunchTemplateData.SecurityGroups
76
- SET version.lastupdated = $update_tag,
77
- version.region=$Region
78
- WITH template, version
79
- MERGE (template)-[r:VERSION]->(version)
80
- ON CREATE SET r.firstseen = timestamp()
81
- SET r.lastupdated = $update_tag
82
- """
83
- for lt in data:
84
- lt['CreateTime'] = str(int(lt['CreateTime'].timestamp()))
85
- for tv in lt["_template_versions"]:
86
- tv['CreateTime'] = str(int(tv['CreateTime'].timestamp()))
87
-
88
- neo4j_session.run(
89
- ingest_lt,
90
- launch_templates=data,
91
- AWS_ACCOUNT_ID=current_aws_account_id,
45
+ load(
46
+ neo4j_session,
47
+ LaunchTemplateSchema(),
48
+ data,
92
49
  Region=region,
93
- update_tag=update_tag,
50
+ AWS_ID=current_aws_account_id,
51
+ lastupdated=update_tag,
94
52
  )
95
53
 
96
54
 
97
55
  @timeit
98
- def cleanup_ec2_launch_templates(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
99
- run_cleanup_job(
100
- 'aws_import_ec2_launch_templates_cleanup.json',
56
+ @aws_handle_regions
57
+ def get_launch_template_versions(
58
+ boto3_session: boto3.session.Session,
59
+ templates: list[dict[str, Any]],
60
+ region: str,
61
+ ) -> list[dict[str, Any]]:
62
+ client = boto3_session.client('ec2', region_name=region, config=get_botocore_config())
63
+ v_paginator = client.get_paginator('describe_launch_template_versions')
64
+ template_versions = []
65
+ for template in templates:
66
+ for versions in v_paginator.paginate(LaunchTemplateId=template['LaunchTemplateId']):
67
+ template_versions.extend(versions['LaunchTemplateVersions'])
68
+ return template_versions
69
+
70
+
71
+ def transform_launch_template_versions(versions: list[dict[str, Any]]) -> list[dict[str, Any]]:
72
+ result: list[dict[str, Any]] = []
73
+ for version in versions:
74
+ current = version.copy()
75
+
76
+ # Reformat some fields
77
+ current['Id'] = f"{version['LaunchTemplateId']}-{version['VersionNumber']}"
78
+ current['CreateTime'] = str(int(version['CreateTime'].timestamp()))
79
+
80
+ # Handle the nested object returned from boto
81
+ ltd = version['LaunchTemplateData']
82
+ current['KernelId'] = ltd.get('KernelId')
83
+ current['EbsOptimized'] = ltd.get('EbsOptimized')
84
+ current['IamInstanceProfileArn'] = ltd.get('IamInstanceProfileArn')
85
+ current['IamInstanceProfileName'] = ltd.get('IamInstanceProfileName')
86
+ current['ImageId'] = ltd.get('ImageId')
87
+ current['InstanceType'] = ltd.get('InstanceType')
88
+ current['KeyName'] = ltd.get('KeyName')
89
+ current['MonitoringEnabled'] = ltd.get('MonitoringEnabled')
90
+ current['RamdiskId'] = ltd.get('RamdiskId')
91
+ current['DisableApiTermination'] = ltd.get('DisableApiTermination')
92
+ current['InstanceInitiatedShutDownBehavior'] = ltd.get('InstanceInitiatedShutDownBehavior')
93
+ current['SecurityGroupIds'] = ltd.get('SecurityGroupIds')
94
+ current['SecurityGroups'] = ltd.get('SecurityGroups')
95
+ result.append(current)
96
+ return result
97
+
98
+
99
+ @timeit
100
+ def load_launch_template_versions(
101
+ neo4j_session: neo4j.Session,
102
+ data: list[dict[str, Any]],
103
+ region: str,
104
+ current_aws_account_id: str,
105
+ update_tag: int,
106
+ ) -> None:
107
+ load(
101
108
  neo4j_session,
102
- common_job_parameters,
109
+ LaunchTemplateVersionSchema(),
110
+ data,
111
+ Region=region,
112
+ AWS_ID=current_aws_account_id,
113
+ lastupdated=update_tag,
103
114
  )
104
115
 
105
116
 
106
117
  @timeit
107
118
  def sync_ec2_launch_templates(
108
- neo4j_session: neo4j.Session, boto3_session: boto3.session.Session, regions: List[str],
109
- current_aws_account_id: str, update_tag: int, common_job_parameters: Dict,
119
+ neo4j_session: neo4j.Session,
120
+ boto3_session: boto3.session.Session,
121
+ regions: list[str],
122
+ current_aws_account_id: str,
123
+ update_tag: int,
124
+ common_job_parameters: dict[str, Any],
110
125
  ) -> None:
111
126
  for region in regions:
112
- logger.debug("Syncing launch templates for region '%s' in account '%s'.", region, current_aws_account_id)
113
- data = get_launch_templates(boto3_session, region)
114
- load_launch_templates(neo4j_session, data, region, current_aws_account_id, update_tag)
115
- cleanup_ec2_launch_templates(neo4j_session, common_job_parameters)
127
+ logger.info(f"Syncing launch templates for region '{region}' in account '{current_aws_account_id}'.")
128
+ templates = get_launch_templates(boto3_session, region)
129
+ templates = transform_launch_templates(templates)
130
+ load_launch_templates(neo4j_session, templates, region, current_aws_account_id, update_tag)
131
+
132
+ versions = get_launch_template_versions(boto3_session, templates, region)
133
+ versions = transform_launch_template_versions(versions)
134
+ load_launch_template_versions(neo4j_session, versions, region, current_aws_account_id, update_tag)
@@ -68,7 +68,7 @@ def start_okta_ingestion(neo4j_session: neo4j.Session, config: Config) -> None:
68
68
  applications.sync_okta_applications(neo4j_session, config.okta_org_id, config.update_tag, config.okta_api_key)
69
69
  factors.sync_users_factors(neo4j_session, config.okta_org_id, config.update_tag, config.okta_api_key, state)
70
70
  origins.sync_trusted_origins(neo4j_session, config.okta_org_id, config.update_tag, config.okta_api_key)
71
- awssaml.sync_okta_aws_saml(neo4j_session, config.okta_saml_role_regex, config.update_tag)
71
+ awssaml.sync_okta_aws_saml(neo4j_session, config.okta_saml_role_regex, config.update_tag, config.okta_org_id)
72
72
 
73
73
  # need creds with permission
74
74
  # soft fail as some won't be able to get such high priv token
@@ -1,15 +1,22 @@
1
1
  # Okta intel module - AWS SAML
2
2
  import logging
3
3
  import re
4
+ from collections import namedtuple
4
5
  from typing import Dict
5
6
  from typing import List
6
7
  from typing import Optional
7
8
 
8
9
  import neo4j
9
10
 
11
+ from cartography.client.core.tx import read_list_of_dicts_tx
12
+ from cartography.client.core.tx import read_single_value_tx
10
13
  from cartography.util import timeit
11
14
 
12
15
 
16
+ AccountRole = namedtuple('AccountRole', ['account_id', 'role_name'])
17
+ OktaGroup = namedtuple('OktaGroup', ['group_id', 'group_name'])
18
+ GroupRole = namedtuple('GroupRole', ['okta_group_id', 'aws_role_arn'])
19
+
13
20
  logger = logging.getLogger(__name__)
14
21
 
15
22
 
@@ -17,17 +24,25 @@ def _parse_regex(regex_string: str) -> str:
17
24
  return regex_string.replace("{{accountid}}", "P<accountid>").replace("{{role}}", "P<role>").strip()
18
25
 
19
26
 
20
- @timeit
21
- def transform_okta_group_to_aws_role(group_id: str, group_name: str, mapping_regex: str) -> Optional[Dict]:
27
+ def _parse_okta_group_name(okta_group_name: str, mapping_regex: str) -> AccountRole | None:
28
+ """
29
+ Extract AWS account id and AWS role name from the given Okta group name using the given mapping regex.
30
+ """
22
31
  regex = _parse_regex(mapping_regex)
23
- matches = re.search(regex, group_name)
32
+ matches = re.search(regex, okta_group_name)
24
33
  if matches:
25
- accountid = matches.group("accountid")
26
- role = matches.group("role")
27
- role_arn = f"arn:aws:iam::{accountid}:role/{role}"
34
+ account_id = matches.group("accountid")
35
+ role_name = matches.group("role")
36
+ return AccountRole(account_id, role_name)
37
+ return None
38
+
39
+
40
+ def transform_okta_group_to_aws_role(group_id: str, group_name: str, mapping_regex: str) -> Optional[Dict]:
41
+ account_role = _parse_okta_group_name(group_name, mapping_regex)
42
+ if account_role:
43
+ role_arn = f"arn:aws:iam::{account_role.account_id}:role/{account_role.role_name}"
28
44
  return {"groupid": group_id, "role": role_arn}
29
- else:
30
- return None
45
+ return None
31
46
 
32
47
 
33
48
  @timeit
@@ -45,6 +60,7 @@ def query_for_okta_to_aws_role_mapping(neo4j_session: neo4j.Session, mapping_reg
45
60
 
46
61
  for res in results:
47
62
  has_results = True
63
+ # input: okta group id, okta group name. output: aws role arn.
48
64
  mapping = transform_okta_group_to_aws_role(res["group.id"], res["group.name"], mapping_regex)
49
65
  if mapping:
50
66
  group_to_role_mapping.append(mapping)
@@ -107,8 +123,96 @@ def _load_human_can_assume_role(neo4j_session: neo4j.Session, okta_update_tag: i
107
123
  )
108
124
 
109
125
 
126
+ def get_awssso_okta_groups(neo4j_session: neo4j.Session, okta_org_id: str) -> list[OktaGroup]:
127
+ """
128
+ Return list of all Okta group ids in the current Okta organization tied to Okta Applications with name
129
+ "amazon_aws_sso".
130
+ """
131
+ query = """
132
+ MATCH (g:OktaGroup)-[:APPLICATION]->(a:OktaApplication{name:"amazon_aws_sso"})
133
+ <-[:RESOURCE]-(:OktaOrganization{id: $okta_org_id})
134
+ RETURN g.id as group_id, g.name as group_name
135
+ """
136
+ result = neo4j_session.read_transaction(read_list_of_dicts_tx, query, okta_org_id=okta_org_id)
137
+ return [OktaGroup(group_name=og['group_name'], group_id=og['group_id']) for og in result]
138
+
139
+
140
+ def get_awssso_role_arn(account_id: str, role_hint: str, neo4j_session: neo4j.Session) -> str | None:
141
+ """
142
+ Attempt to return the AWS role ARN for the given AWS account ID and role hint string.
143
+ This function exists to handle that AWS SSO roles have a 'AWSReservedSSO' prefix and a hashed suffix
144
+ Input:
145
+ - account_id: AWS account ID
146
+ - role_hint (str): The `AccountRole.role_name` returned by _parse_okta_group_name(). This is the part of the Okta
147
+ group name that refers to the AWS role name.
148
+ Output:
149
+ - If we are able to find it, returns the matching AWS role ARN.
150
+ """
151
+ query = """
152
+ MATCH (:AWSAccount{id:$account_id})-[:RESOURCE]->(role:AWSRole{path:"/aws-reserved/sso.amazonaws.com/"})
153
+ WHERE SPLIT(role.name, '_')[1..-1][0] = $role_hint
154
+ RETURN role.arn AS role_arn
155
+ """
156
+ return neo4j_session.read_transaction(read_single_value_tx, query, account_id=account_id, role_hint=role_hint)
157
+
158
+
159
+ def query_for_okta_to_awssso_role_mapping(
160
+ neo4j_session: neo4j.Session,
161
+ awssso_okta_groups: list[OktaGroup],
162
+ mapping_regex: str,
163
+ ) -> list[GroupRole]:
164
+ """
165
+ Input:
166
+ - neo4j session
167
+ - str list of Okta group names
168
+ - str regex that tells us how to find the AWS role name and account when given an Okta group name
169
+ Output:
170
+ - list of OktaGroup id to AWSRole arn pairs.
171
+ """
172
+ result = []
173
+ for group in awssso_okta_groups:
174
+ account_role = _parse_okta_group_name(group.group_name, mapping_regex)
175
+ if not account_role:
176
+ logger.info(f"Okta group {group.group_name} has no associated AWS SSO role")
177
+ continue
178
+
179
+ role_arn = get_awssso_role_arn(account_role.account_id, account_role.role_name, neo4j_session)
180
+ if role_arn:
181
+ result.append(GroupRole(group.group_id, role_arn))
182
+ return result
183
+
184
+
185
+ def _load_awssso_tx(tx: neo4j.Transaction, group_to_role: list[GroupRole], okta_update_tag: int) -> None:
186
+ ingest_statement = """
187
+ UNWIND $GROUP_TO_ROLE as app_data
188
+ MATCH (role:AWSRole{arn: app_data.aws_role_arn})
189
+ MATCH (group:OktaGroup{id: app_data.okta_group_id})
190
+ MERGE (role)<-[r:ALLOWED_BY]-(group)
191
+ ON CREATE SET r.firstseen = timestamp()
192
+ SET r.lastupdated = $okta_update_tag
193
+ """
194
+ tx.run(
195
+ ingest_statement,
196
+ GROUP_TO_ROLE=[g._asdict() for g in group_to_role],
197
+ okta_update_tag=okta_update_tag,
198
+ )
199
+
200
+
201
+ def _load_okta_group_to_awssso_roles(
202
+ neo4j_session: neo4j.Session,
203
+ group_to_role: list[GroupRole],
204
+ okta_update_tag: int,
205
+ ) -> None:
206
+ neo4j_session.write_transaction(_load_awssso_tx, group_to_role, okta_update_tag)
207
+
208
+
110
209
  @timeit
111
- def sync_okta_aws_saml(neo4j_session: neo4j.Session, mapping_regex: str, okta_update_tag: int) -> None:
210
+ def sync_okta_aws_saml(
211
+ neo4j_session: neo4j.Session,
212
+ mapping_regex: str,
213
+ okta_update_tag: int,
214
+ okta_org_id: str,
215
+ ) -> None:
112
216
  """
113
217
  Sync okta integration with saml. This will link OktaGroups to the AWSRoles they enable.
114
218
  This is for people who use the okta saml provider for AWS
@@ -127,3 +231,7 @@ def sync_okta_aws_saml(neo4j_session: neo4j.Session, mapping_regex: str, okta_up
127
231
  group_to_role_mapping = query_for_okta_to_aws_role_mapping(neo4j_session, mapping_regex)
128
232
  _load_okta_group_to_aws_roles(neo4j_session, group_to_role_mapping, okta_update_tag)
129
233
  _load_human_can_assume_role(neo4j_session, okta_update_tag)
234
+
235
+ sso_okta_groups = get_awssso_okta_groups(neo4j_session, okta_org_id)
236
+ group_to_ssorole_mapping = query_for_okta_to_awssso_role_mapping(neo4j_session, sso_okta_groups, mapping_regex)
237
+ _load_okta_group_to_awssso_roles(neo4j_session, group_to_ssorole_mapping, okta_update_tag)
@@ -0,0 +1,81 @@
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 LaunchTemplateVersionNodeProperties(CartographyNodeProperties):
16
+ id: PropertyRef = PropertyRef('Id')
17
+ name: PropertyRef = PropertyRef('LaunchTemplateName')
18
+ create_time: PropertyRef = PropertyRef('CreateTime')
19
+ created_by: PropertyRef = PropertyRef('CreatedBy')
20
+ default_version: PropertyRef = PropertyRef('DefaultVersion')
21
+ version_number: PropertyRef = PropertyRef('VersionNumber')
22
+ version_description: PropertyRef = PropertyRef('VersionDescription')
23
+ kernel_id: PropertyRef = PropertyRef('KernelId')
24
+ ebs_optimized: PropertyRef = PropertyRef('EbsOptimized')
25
+ iam_instance_profile_arn: PropertyRef = PropertyRef('IamInstanceProfileArn')
26
+ iam_instance_profile_name: PropertyRef = PropertyRef('IamInstanceProfileName')
27
+ image_id: PropertyRef = PropertyRef('ImageId')
28
+ instance_type: PropertyRef = PropertyRef('InstanceType')
29
+ key_name: PropertyRef = PropertyRef('KeyName')
30
+ monitoring_enabled: PropertyRef = PropertyRef('MonitoringEnabled')
31
+ ramdisk_id: PropertyRef = PropertyRef('RamdiskId')
32
+ disable_api_termination: PropertyRef = PropertyRef('DisableApiTermination')
33
+ instance_initiated_shutdown_behavior: PropertyRef = PropertyRef('InstanceInitiatedShutdownBehavior')
34
+ security_group_ids: PropertyRef = PropertyRef('SecurityGroupIds')
35
+ security_groups: PropertyRef = PropertyRef('SecurityGroups')
36
+ region: PropertyRef = PropertyRef('Region', set_in_kwargs=True)
37
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class LaunchTemplateVersionToAwsAccountRelProperties(CartographyRelProperties):
42
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
43
+
44
+
45
+ @dataclass(frozen=True)
46
+ class LaunchTemplateVersionToAWSAccount(CartographyRelSchema):
47
+ target_node_label: str = 'AWSAccount'
48
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
49
+ {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
50
+ )
51
+ direction: LinkDirection = LinkDirection.INWARD
52
+ rel_label: str = "RESOURCE"
53
+ properties: LaunchTemplateVersionToAwsAccountRelProperties = LaunchTemplateVersionToAwsAccountRelProperties()
54
+
55
+
56
+ @dataclass(frozen=True)
57
+ class LaunchTemplateVersionToLTRelProperties(CartographyRelProperties):
58
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
59
+
60
+
61
+ @dataclass(frozen=True)
62
+ class LaunchTemplateVersionToLT(CartographyRelSchema):
63
+ target_node_label: str = 'LaunchTemplate'
64
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
65
+ {'id': PropertyRef('LaunchTemplateId')},
66
+ )
67
+ direction: LinkDirection = LinkDirection.INWARD
68
+ rel_label: str = "VERSION"
69
+ properties: LaunchTemplateVersionToLTRelProperties = LaunchTemplateVersionToLTRelProperties()
70
+
71
+
72
+ @dataclass(frozen=True)
73
+ class LaunchTemplateVersionSchema(CartographyNodeSchema):
74
+ label: str = 'LaunchTemplateVersion'
75
+ properties: LaunchTemplateVersionNodeProperties = LaunchTemplateVersionNodeProperties()
76
+ sub_resource_relationship: LaunchTemplateVersionToAWSAccount = LaunchTemplateVersionToAWSAccount()
77
+ other_relationships: OtherRelationships = OtherRelationships(
78
+ [
79
+ LaunchTemplateVersionToLT(),
80
+ ],
81
+ )
@@ -0,0 +1,46 @@
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 LaunchTemplateNodeProperties(CartographyNodeProperties):
15
+ id: PropertyRef = PropertyRef('LaunchTemplateId')
16
+ launch_template_id: PropertyRef = PropertyRef('LaunchTemplateId')
17
+ name: PropertyRef = PropertyRef('LaunchTemplateName')
18
+ create_time: PropertyRef = PropertyRef('CreateTime')
19
+ created_by: PropertyRef = PropertyRef('CreatedBy')
20
+ default_version_number: PropertyRef = PropertyRef('DefaultVersionNumber')
21
+ latest_version_number: PropertyRef = PropertyRef('LatestVersionNumber')
22
+ region: PropertyRef = PropertyRef('Region', set_in_kwargs=True)
23
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
24
+
25
+
26
+ @dataclass(frozen=True)
27
+ class LaunchTemplateToAwsAccountRelProperties(CartographyRelProperties):
28
+ lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
29
+
30
+
31
+ @dataclass(frozen=True)
32
+ class LaunchTemplateToAWSAccount(CartographyRelSchema):
33
+ target_node_label: str = 'AWSAccount'
34
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
35
+ {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
36
+ )
37
+ direction: LinkDirection = LinkDirection.INWARD
38
+ rel_label: str = "RESOURCE"
39
+ properties: LaunchTemplateToAwsAccountRelProperties = LaunchTemplateToAwsAccountRelProperties()
40
+
41
+
42
+ @dataclass(frozen=True)
43
+ class LaunchTemplateSchema(CartographyNodeSchema):
44
+ label: str = 'LaunchTemplate'
45
+ properties: LaunchTemplateNodeProperties = LaunchTemplateNodeProperties()
46
+ sub_resource_relationship: LaunchTemplateToAWSAccount = LaunchTemplateToAWSAccount()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cartography
3
- Version: 0.91.0
3
+ Version: 0.92.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
@@ -12,7 +12,7 @@ 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=4_kTBxrtlwsOM-e8Xtjf7wmmzwZ-DGRJL0rPFp0Xj0Q,10805
14
14
  cartography/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- cartography/data/indexes.cypher,sha256=2OP2V7hsN794IssfeaAYYwPxUt5QghXnrgBAEKHWag8,27804
15
+ cartography/data/indexes.cypher,sha256=PTQEUbC_Kmjj_wM-j6NJqLvETRIORreeqF6WlKmnHKg,27395
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
@@ -36,7 +36,6 @@ cartography/data/jobs/cleanup/aws_import_account_access_key_cleanup.json,sha256=
36
36
  cartography/data/jobs/cleanup/aws_import_apigateway_cleanup.json,sha256=wCV95ydo3dmlhK7VrDrxCqrP6dbhCCMTzcz_qaJQ4Jo,2189
37
37
  cartography/data/jobs/cleanup/aws_import_config_cleanup.json,sha256=VCAJjEnFcQUR16VxKdpsOkBJEnhMuLk-7Kgm_p9k1NM,754
38
38
  cartography/data/jobs/cleanup/aws_import_ec2_launch_configurations_cleanup.json,sha256=x9IIzb9Sr1353ygkA-qqUUbZS9XO2v3GzUHe-0J4Pw8,281
39
- cartography/data/jobs/cleanup/aws_import_ec2_launch_templates_cleanup.json,sha256=tuJzb1wmKSPUiShX8zgNTz7Il_XhXZ7_uQE4_6iUjFI,524
40
39
  cartography/data/jobs/cleanup/aws_import_ec2_security_groupinfo_cleanup.json,sha256=CackEgSs1PN15pTg8oIdS0amB-n-PsKODLAaqC3gf_A,1183
41
40
  cartography/data/jobs/cleanup/aws_import_ecr_cleanup.json,sha256=7Sga9WlbhHe-VyoFaF0LrlhbAFvSSOjVKiRf_VW8To8,1355
42
41
  cartography/data/jobs/cleanup/aws_import_ecs_cleanup.json,sha256=6HtmZy7gNC0ZxLU7I6C2KKcqpZhYRFyaJZCDA50DzAs,2126
@@ -176,7 +175,7 @@ cartography/intel/aws/ec2/images.py,sha256=DcGHJwZf8_K5iRCDJ2QOdP837TTJTwST02IRs
176
175
  cartography/intel/aws/ec2/instances.py,sha256=mnTjdBY-4D-TGhH29UrSaLUW0Uft0JApDIJkkLz4zPc,12170
177
176
  cartography/intel/aws/ec2/internet_gateways.py,sha256=dI-4-85_3DGGZZBcY_DN6XqESx9P26S6jKok314lcnQ,2883
178
177
  cartography/intel/aws/ec2/key_pairs.py,sha256=SvRgd56vE4eouvTSNoFK8PP8HYoECO91goxc36oq_FY,2508
179
- cartography/intel/aws/ec2/launch_templates.py,sha256=UXqINdxBzpgPTJVjSZ9DXhO-Lo598aHswJapuo4QNXA,5099
178
+ cartography/intel/aws/ec2/launch_templates.py,sha256=GSOtwvqL6pG2fcROhhjXjOPntW-nR8msT-dQG_JuQkM,4862
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
182
181
  cartography/intel/aws/ec2/network_interfaces.py,sha256=CzF8PooCYUQ2pk8DR8JDAhkWRUQSBj_27OsIfkL_-Cs,9199
@@ -253,9 +252,9 @@ cartography/intel/oci/__init__.py,sha256=AZmRX6EO4LUnynDtIKHxtZ_Ab2-CYPPc2u5d0Q2
253
252
  cartography/intel/oci/iam.py,sha256=zPrJeoMoO3ZkjBfWbTttjrcUvxxMuWquLTmsDH5MgOI,17712
254
253
  cartography/intel/oci/organizations.py,sha256=tzQkZfE4LPoS-6lXBRQGyhq8aJLZUJ1_q75Q9eTBke0,4086
255
254
  cartography/intel/oci/utils.py,sha256=UbX9jib4sWEdKeAt2CeCo4k9shUiWY08oTfQz_nDvjA,3223
256
- cartography/intel/okta/__init__.py,sha256=HYw9wlE27dHJ2fwSlHgbJyHcxhdFzbYWBcZdQ6bqfIo,3813
255
+ cartography/intel/okta/__init__.py,sha256=i5YY9mIDQ2-IBnCSWf4rToYMa9fQQIxucCnl0TXK2Uc,3833
257
256
  cartography/intel/okta/applications.py,sha256=ZqUn-bru6Kh75vpUeRnMurUBh0rGBRpI2b2V09HOOQw,12866
258
- cartography/intel/okta/awssaml.py,sha256=uJFasoyQmABoC5xAjlXak51KuAjT2H6AA2f47N3h6gw,4651
257
+ cartography/intel/okta/awssaml.py,sha256=Rw0mrJ7NY5xjfEO_ijMqi1VEbr0FSasfrvGtoCPy1aU,9136
259
258
  cartography/intel/okta/factors.py,sha256=1bLnF4MRf0MYzzhT2tfM4jdfkjE1bkQn6_WuOqED2K4,4955
260
259
  cartography/intel/okta/groups.py,sha256=GxaixbY5KWkalj2rY6nWwe_IskVVowOAPo88OZIGcPY,10172
261
260
  cartography/intel/okta/organization.py,sha256=YLQc7ETdtf8Vc-CRCYivV_xmVl2Oz0Px53anJHYp-p8,821
@@ -283,6 +282,8 @@ cartography/models/aws/ec2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
283
282
  cartography/models/aws/ec2/images.py,sha256=uGhXS7Xb6sKUdwwkS0O0dWP4sIREjusUaV_unODv9gE,3012
284
283
  cartography/models/aws/ec2/instances.py,sha256=cNMHngdGNRhxoyID6AmG2F7CQGC1fYani8DV8lSKvsI,3902
285
284
  cartography/models/aws/ec2/keypairs.py,sha256=scKC3SdExHAWkPNmb6tT9LK-9q4sweqS2ejFzMec10M,2630
285
+ cartography/models/aws/ec2/launch_template_versions.py,sha256=RitfnAuAj0XpFsCXkRbtUhHMAi8Vsvmtury231eKvGU,3897
286
+ cartography/models/aws/ec2/launch_templates.py,sha256=GqiwFuMp72LNSt2eQlp2WfdU_vHsom-xKV5AaUewSHQ,2157
286
287
  cartography/models/aws/ec2/loadbalancerv2.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
287
288
  cartography/models/aws/ec2/networkinterface_instance.py,sha256=t3oqcQ4GjYf7dwqPUGCiXd70ie4ibYLilOXiE5_Ad8g,4707
288
289
  cartography/models/aws/ec2/networkinterfaces.py,sha256=z1-Dl6I79-TCxXKG8QBpSKga93lPCPaLR1XqKJZK3ME,4127
@@ -331,10 +332,10 @@ cartography/models/semgrep/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
331
332
  cartography/models/semgrep/deployment.py,sha256=or5qZDuR51MXzINpH15jZrqmSUvXQevCNYWJ7D6v-JI,745
332
333
  cartography/models/semgrep/findings.py,sha256=xrn8sgXpNMrNJbKQagaAVxaCG9bVjTATSRR2XRBR4rg,5386
333
334
  cartography/models/semgrep/locations.py,sha256=kSk7Nn5Mn4Ob84MVZOo2GR0YFi-9Okq9pgA3FfC6_bk,3061
334
- cartography-0.91.0.dist-info/LICENSE,sha256=489ZXeW9G90up6ep-D1n-lJgk9ciNT2yxXpFgRSidtk,11341
335
- cartography-0.91.0.dist-info/METADATA,sha256=IhgPXxZ4hfyjHAZyMjHdBkM8_s8XmHDgOJMEyOKXgBI,1988
336
- cartography-0.91.0.dist-info/NOTICE,sha256=YOGAsjFtbyKj5tslYIg6V5jEYRuEvnSsIuDOUKj0Qj4,97
337
- cartography-0.91.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
338
- cartography-0.91.0.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
339
- cartography-0.91.0.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
340
- cartography-0.91.0.dist-info/RECORD,,
335
+ cartography-0.92.0rc2.dist-info/LICENSE,sha256=489ZXeW9G90up6ep-D1n-lJgk9ciNT2yxXpFgRSidtk,11341
336
+ cartography-0.92.0rc2.dist-info/METADATA,sha256=67pexbhOi_WeS7TLuIGswFYPCfMbzOz6eSibk8FgvUo,1991
337
+ cartography-0.92.0rc2.dist-info/NOTICE,sha256=YOGAsjFtbyKj5tslYIg6V5jEYRuEvnSsIuDOUKj0Qj4,97
338
+ cartography-0.92.0rc2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
339
+ cartography-0.92.0rc2.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
340
+ cartography-0.92.0rc2.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
341
+ cartography-0.92.0rc2.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- {
2
- "statements": [{
3
- "query": "MATCH (n:LaunchTemplateVersion)<-[:VERSION]-(:LaunchTemplate)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ID}) 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:LaunchTemplate)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ID}) WHERE n.lastupdated <> $UPDATE_TAG WITH n LIMIT $LIMIT_SIZE DETACH DELETE (n)",
9
- "iterative": true,
10
- "iterationsize": 100
11
- }],
12
- "name": "cleanup LaunchTemplate"
13
- }