cartography 0.107.0rc2__py3-none-any.whl → 0.108.0__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 +2 -2
- cartography/cli.py +10 -0
- cartography/config.py +5 -0
- cartography/data/indexes.cypher +0 -10
- cartography/data/jobs/cleanup/github_repos_cleanup.json +2 -0
- cartography/intel/aws/__init__.py +1 -0
- cartography/intel/aws/cloudtrail.py +17 -4
- cartography/intel/aws/cloudtrail_management_events.py +560 -16
- cartography/intel/aws/cloudwatch.py +150 -4
- cartography/intel/aws/ec2/security_groups.py +140 -122
- cartography/intel/aws/ec2/snapshots.py +47 -84
- cartography/intel/aws/ec2/subnets.py +37 -63
- cartography/intel/aws/ecr.py +55 -80
- cartography/intel/aws/ecs.py +17 -0
- cartography/intel/aws/elasticache.py +102 -79
- cartography/intel/aws/guardduty.py +275 -0
- cartography/intel/aws/resources.py +2 -0
- cartography/intel/aws/secretsmanager.py +62 -44
- cartography/intel/github/repos.py +370 -28
- cartography/intel/sentinelone/__init__.py +8 -2
- cartography/intel/sentinelone/application.py +248 -0
- cartography/intel/sentinelone/utils.py +20 -1
- cartography/models/aws/cloudtrail/management_events.py +95 -6
- cartography/models/aws/cloudtrail/trail.py +21 -0
- cartography/models/aws/cloudwatch/log_metric_filter.py +79 -0
- cartography/models/aws/cloudwatch/metric_alarm.py +53 -0
- cartography/models/aws/ec2/networkinterfaces.py +2 -0
- cartography/models/aws/ec2/security_group_rules.py +109 -0
- cartography/models/aws/ec2/security_groups.py +90 -0
- cartography/models/aws/ec2/snapshots.py +58 -0
- cartography/models/aws/ec2/subnet_instance.py +2 -0
- cartography/models/aws/ec2/subnet_networkinterface.py +2 -0
- cartography/models/aws/ec2/subnets.py +65 -0
- cartography/models/aws/ec2/volumes.py +20 -0
- cartography/models/aws/ecr/__init__.py +0 -0
- cartography/models/aws/ecr/image.py +41 -0
- cartography/models/aws/ecr/repository.py +72 -0
- cartography/models/aws/ecr/repository_image.py +95 -0
- cartography/models/aws/ecs/tasks.py +24 -1
- cartography/models/aws/elasticache/__init__.py +0 -0
- cartography/models/aws/elasticache/cluster.py +65 -0
- cartography/models/aws/elasticache/topic.py +67 -0
- cartography/models/aws/guardduty/__init__.py +1 -0
- cartography/models/aws/guardduty/findings.py +102 -0
- cartography/models/aws/secretsmanager/secret.py +106 -0
- cartography/models/github/dependencies.py +74 -0
- cartography/models/github/manifests.py +49 -0
- cartography/models/sentinelone/application.py +44 -0
- cartography/models/sentinelone/application_version.py +96 -0
- {cartography-0.107.0rc2.dist-info → cartography-0.108.0.dist-info}/METADATA +3 -3
- {cartography-0.107.0rc2.dist-info → cartography-0.108.0.dist-info}/RECORD +55 -36
- cartography/data/jobs/cleanup/aws_import_ec2_security_groupinfo_cleanup.json +0 -24
- cartography/data/jobs/cleanup/aws_import_secrets_cleanup.json +0 -8
- cartography/data/jobs/cleanup/aws_import_snapshots_cleanup.json +0 -30
- {cartography-0.107.0rc2.dist-info → cartography-0.108.0.dist-info}/WHEEL +0 -0
- {cartography-0.107.0rc2.dist-info → cartography-0.108.0.dist-info}/entry_points.txt +0 -0
- {cartography-0.107.0rc2.dist-info → cartography-0.108.0.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.107.0rc2.dist-info → cartography-0.108.0.dist-info}/top_level.txt +0 -0
|
@@ -9,7 +9,11 @@ import neo4j
|
|
|
9
9
|
from cartography.client.core.tx import load
|
|
10
10
|
from cartography.graph.job import GraphJob
|
|
11
11
|
from cartography.intel.aws.ec2.util import get_botocore_config
|
|
12
|
+
from cartography.models.aws.cloudwatch.log_metric_filter import (
|
|
13
|
+
CloudWatchLogMetricFilterSchema,
|
|
14
|
+
)
|
|
12
15
|
from cartography.models.aws.cloudwatch.loggroup import CloudWatchLogGroupSchema
|
|
16
|
+
from cartography.models.aws.cloudwatch.metric_alarm import CloudWatchMetricAlarmSchema
|
|
13
17
|
from cartography.util import aws_handle_regions
|
|
14
18
|
from cartography.util import timeit
|
|
15
19
|
|
|
@@ -31,6 +35,84 @@ def get_cloudwatch_log_groups(
|
|
|
31
35
|
return logGroups
|
|
32
36
|
|
|
33
37
|
|
|
38
|
+
@timeit
|
|
39
|
+
@aws_handle_regions
|
|
40
|
+
def get_cloudwatch_log_metric_filters(
|
|
41
|
+
boto3_session: boto3.Session, region: str
|
|
42
|
+
) -> List[Dict[str, Any]]:
|
|
43
|
+
logs_client = boto3_session.client(
|
|
44
|
+
"logs", region_name=region, config=get_botocore_config()
|
|
45
|
+
)
|
|
46
|
+
paginator = logs_client.get_paginator("describe_metric_filters")
|
|
47
|
+
metric_filters = []
|
|
48
|
+
|
|
49
|
+
for page in paginator.paginate():
|
|
50
|
+
metric_filters.extend(page.get("metricFilters", []))
|
|
51
|
+
|
|
52
|
+
return metric_filters
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def transform_metric_filters(
|
|
56
|
+
metric_filters: List[Dict[str, Any]], region: str
|
|
57
|
+
) -> List[Dict[str, Any]]:
|
|
58
|
+
"""
|
|
59
|
+
Transform CloudWatch log metric filter data for ingestion into Neo4j.
|
|
60
|
+
Ensures that the 'id' field is a unique combination of logGroupName and filterName.
|
|
61
|
+
"""
|
|
62
|
+
transformed_filters = []
|
|
63
|
+
for filter in metric_filters:
|
|
64
|
+
transformed_filter = {
|
|
65
|
+
"id": f"{filter['logGroupName']}:{filter['filterName']}",
|
|
66
|
+
"arn": f"{filter['logGroupName']}:{filter['filterName']}",
|
|
67
|
+
"filterName": filter["filterName"],
|
|
68
|
+
"filterPattern": filter.get("filterPattern"),
|
|
69
|
+
"logGroupName": filter["logGroupName"],
|
|
70
|
+
"metricName": filter["metricTransformations"][0]["metricName"],
|
|
71
|
+
"metricNamespace": filter["metricTransformations"][0]["metricNamespace"],
|
|
72
|
+
"metricValue": filter["metricTransformations"][0]["metricValue"],
|
|
73
|
+
"Region": region,
|
|
74
|
+
}
|
|
75
|
+
transformed_filters.append(transformed_filter)
|
|
76
|
+
return transformed_filters
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@timeit
|
|
80
|
+
@aws_handle_regions
|
|
81
|
+
def get_cloudwatch_metric_alarms(
|
|
82
|
+
boto3_session: boto3.Session, region: str
|
|
83
|
+
) -> List[Dict[str, Any]]:
|
|
84
|
+
client = boto3_session.client(
|
|
85
|
+
"cloudwatch", region_name=region, config=get_botocore_config()
|
|
86
|
+
)
|
|
87
|
+
paginator = client.get_paginator("describe_alarms")
|
|
88
|
+
alarms = []
|
|
89
|
+
for page in paginator.paginate():
|
|
90
|
+
alarms.extend(page["MetricAlarms"])
|
|
91
|
+
return alarms
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def transform_metric_alarms(
|
|
95
|
+
metric_alarms: List[Dict[str, Any]], region: str
|
|
96
|
+
) -> List[Dict[str, Any]]:
|
|
97
|
+
"""
|
|
98
|
+
Transform CloudWatch metric alarm data for ingestion into Neo4j.
|
|
99
|
+
"""
|
|
100
|
+
transformed_alarms = []
|
|
101
|
+
for alarm in metric_alarms:
|
|
102
|
+
transformed_alarm = {
|
|
103
|
+
"AlarmArn": alarm["AlarmArn"],
|
|
104
|
+
"AlarmName": alarm.get("AlarmName"),
|
|
105
|
+
"AlarmDescription": alarm.get("AlarmDescription"),
|
|
106
|
+
"StateValue": alarm.get("StateValue"),
|
|
107
|
+
"StateReason": alarm.get("StateReason"),
|
|
108
|
+
"ActionsEnabled": alarm.get("ActionsEnabled"),
|
|
109
|
+
"ComparisonOperator": alarm.get("ComparisonOperator"),
|
|
110
|
+
"Region": region,
|
|
111
|
+
}
|
|
112
|
+
transformed_alarms.append(transformed_alarm)
|
|
113
|
+
return transformed_alarms
|
|
114
|
+
|
|
115
|
+
|
|
34
116
|
@timeit
|
|
35
117
|
def load_cloudwatch_log_groups(
|
|
36
118
|
neo4j_session: neo4j.Session,
|
|
@@ -52,6 +134,48 @@ def load_cloudwatch_log_groups(
|
|
|
52
134
|
)
|
|
53
135
|
|
|
54
136
|
|
|
137
|
+
@timeit
|
|
138
|
+
def load_cloudwatch_log_metric_filters(
|
|
139
|
+
neo4j_session: neo4j.Session,
|
|
140
|
+
data: List[Dict[str, Any]],
|
|
141
|
+
region: str,
|
|
142
|
+
current_aws_account_id: str,
|
|
143
|
+
aws_update_tag: int,
|
|
144
|
+
) -> None:
|
|
145
|
+
logger.info(
|
|
146
|
+
f"Loading CloudWatch {len(data)} log metric filters for region '{region}' into graph.",
|
|
147
|
+
)
|
|
148
|
+
load(
|
|
149
|
+
neo4j_session,
|
|
150
|
+
CloudWatchLogMetricFilterSchema(),
|
|
151
|
+
data,
|
|
152
|
+
lastupdated=aws_update_tag,
|
|
153
|
+
Region=region,
|
|
154
|
+
AWS_ID=current_aws_account_id,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@timeit
|
|
159
|
+
def load_cloudwatch_metric_alarms(
|
|
160
|
+
neo4j_session: neo4j.Session,
|
|
161
|
+
data: List[Dict[str, Any]],
|
|
162
|
+
region: str,
|
|
163
|
+
current_aws_account_id: str,
|
|
164
|
+
aws_update_tag: int,
|
|
165
|
+
) -> None:
|
|
166
|
+
logger.info(
|
|
167
|
+
f"Loading CloudWatch {len(data)} metric alarms for region '{region}' into graph.",
|
|
168
|
+
)
|
|
169
|
+
load(
|
|
170
|
+
neo4j_session,
|
|
171
|
+
CloudWatchMetricAlarmSchema(),
|
|
172
|
+
data,
|
|
173
|
+
lastupdated=aws_update_tag,
|
|
174
|
+
Region=region,
|
|
175
|
+
AWS_ID=current_aws_account_id,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
|
|
55
179
|
@timeit
|
|
56
180
|
def cleanup(
|
|
57
181
|
neo4j_session: neo4j.Session,
|
|
@@ -62,6 +186,12 @@ def cleanup(
|
|
|
62
186
|
CloudWatchLogGroupSchema(), common_job_parameters
|
|
63
187
|
)
|
|
64
188
|
cleanup_job.run(neo4j_session)
|
|
189
|
+
GraphJob.from_node_schema(
|
|
190
|
+
CloudWatchLogMetricFilterSchema(), common_job_parameters
|
|
191
|
+
).run(neo4j_session)
|
|
192
|
+
GraphJob.from_node_schema(CloudWatchMetricAlarmSchema(), common_job_parameters).run(
|
|
193
|
+
neo4j_session
|
|
194
|
+
)
|
|
65
195
|
|
|
66
196
|
|
|
67
197
|
@timeit
|
|
@@ -78,16 +208,32 @@ def sync(
|
|
|
78
208
|
f"Syncing CloudWatch for region '{region}' in account '{current_aws_account_id}'.",
|
|
79
209
|
)
|
|
80
210
|
logGroups = get_cloudwatch_log_groups(boto3_session, region)
|
|
81
|
-
group_data: List[Dict[str, Any]] = []
|
|
82
|
-
for logGroup in logGroups:
|
|
83
|
-
group_data.append(logGroup)
|
|
84
211
|
|
|
85
212
|
load_cloudwatch_log_groups(
|
|
86
213
|
neo4j_session,
|
|
87
|
-
|
|
214
|
+
logGroups,
|
|
215
|
+
region,
|
|
216
|
+
current_aws_account_id,
|
|
217
|
+
update_tag,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
metric_filters = get_cloudwatch_log_metric_filters(boto3_session, region)
|
|
221
|
+
transformed_filters = transform_metric_filters(metric_filters, region)
|
|
222
|
+
load_cloudwatch_log_metric_filters(
|
|
223
|
+
neo4j_session,
|
|
224
|
+
transformed_filters,
|
|
88
225
|
region,
|
|
89
226
|
current_aws_account_id,
|
|
90
227
|
update_tag,
|
|
91
228
|
)
|
|
92
229
|
|
|
230
|
+
metric_alarms = get_cloudwatch_metric_alarms(boto3_session, region)
|
|
231
|
+
transformed_alarms = transform_metric_alarms(metric_alarms, region)
|
|
232
|
+
load_cloudwatch_metric_alarms(
|
|
233
|
+
neo4j_session,
|
|
234
|
+
transformed_alarms,
|
|
235
|
+
region,
|
|
236
|
+
current_aws_account_id,
|
|
237
|
+
update_tag,
|
|
238
|
+
)
|
|
93
239
|
cleanup(neo4j_session, common_job_parameters)
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from
|
|
2
|
+
from collections import namedtuple
|
|
3
|
+
from typing import Any
|
|
3
4
|
from typing import Dict
|
|
4
5
|
from typing import List
|
|
5
6
|
|
|
6
7
|
import boto3
|
|
7
8
|
import neo4j
|
|
8
9
|
|
|
10
|
+
from cartography.client.core.tx import load
|
|
9
11
|
from cartography.graph.job import GraphJob
|
|
12
|
+
from cartography.models.aws.ec2.security_group_rules import IpPermissionInboundSchema
|
|
13
|
+
from cartography.models.aws.ec2.security_group_rules import IpRangeSchema
|
|
14
|
+
from cartography.models.aws.ec2.security_group_rules import IpRuleSchema
|
|
15
|
+
from cartography.models.aws.ec2.security_groups import EC2SecurityGroupSchema
|
|
10
16
|
from cartography.models.aws.ec2.securitygroup_instance import (
|
|
11
17
|
EC2SecurityGroupInstanceSchema,
|
|
12
18
|
)
|
|
13
19
|
from cartography.util import aws_handle_regions
|
|
14
|
-
from cartography.util import run_cleanup_job
|
|
15
20
|
from cartography.util import timeit
|
|
16
21
|
|
|
17
22
|
from .util import get_botocore_config
|
|
@@ -37,138 +42,146 @@ def get_ec2_security_group_data(
|
|
|
37
42
|
return security_groups
|
|
38
43
|
|
|
39
44
|
|
|
45
|
+
Ec2SecurityGroupData = namedtuple(
|
|
46
|
+
"Ec2SecurityGroupData",
|
|
47
|
+
["groups", "inbound_rules", "egress_rules", "ranges"],
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def transform_ec2_security_group_data(
|
|
52
|
+
data: List[Dict[str, Any]],
|
|
53
|
+
) -> Ec2SecurityGroupData:
|
|
54
|
+
groups: List[Dict[str, Any]] = []
|
|
55
|
+
inbound_rules: List[Dict[str, Any]] = []
|
|
56
|
+
egress_rules: List[Dict[str, Any]] = []
|
|
57
|
+
ranges: List[Dict[str, Any]] = []
|
|
58
|
+
|
|
59
|
+
for group in data:
|
|
60
|
+
group_record = {
|
|
61
|
+
"GroupId": group["GroupId"],
|
|
62
|
+
"GroupName": group.get("GroupName"),
|
|
63
|
+
"Description": group.get("Description"),
|
|
64
|
+
"VpcId": group.get("VpcId"),
|
|
65
|
+
}
|
|
66
|
+
# Collect referenced security groups for relationship loading
|
|
67
|
+
source_group_ids: set[str] = set()
|
|
68
|
+
|
|
69
|
+
for rule_type, target in (
|
|
70
|
+
("IpPermissions", inbound_rules),
|
|
71
|
+
("IpPermissionsEgress", egress_rules),
|
|
72
|
+
):
|
|
73
|
+
for rule in group.get(rule_type, []):
|
|
74
|
+
protocol = rule.get("IpProtocol", "all")
|
|
75
|
+
from_port = rule.get("FromPort")
|
|
76
|
+
to_port = rule.get("ToPort")
|
|
77
|
+
rule_id = (
|
|
78
|
+
f"{group['GroupId']}/{rule_type}/{from_port}{to_port}{protocol}"
|
|
79
|
+
)
|
|
80
|
+
target.append(
|
|
81
|
+
{
|
|
82
|
+
"RuleId": rule_id,
|
|
83
|
+
"GroupId": group["GroupId"],
|
|
84
|
+
"Protocol": protocol,
|
|
85
|
+
"FromPort": from_port,
|
|
86
|
+
"ToPort": to_port,
|
|
87
|
+
},
|
|
88
|
+
)
|
|
89
|
+
for ip_range in rule.get("IpRanges", []):
|
|
90
|
+
ranges.append({"RangeId": ip_range["CidrIp"], "RuleId": rule_id})
|
|
91
|
+
for pair in rule.get("UserIdGroupPairs", []):
|
|
92
|
+
sg_id = pair.get("GroupId")
|
|
93
|
+
if sg_id:
|
|
94
|
+
source_group_ids.add(sg_id)
|
|
95
|
+
|
|
96
|
+
group_record["SOURCE_GROUP_IDS"] = list(source_group_ids)
|
|
97
|
+
groups.append(group_record)
|
|
98
|
+
|
|
99
|
+
return Ec2SecurityGroupData(
|
|
100
|
+
groups=groups,
|
|
101
|
+
inbound_rules=inbound_rules,
|
|
102
|
+
egress_rules=egress_rules,
|
|
103
|
+
ranges=ranges,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
40
107
|
@timeit
|
|
41
|
-
def
|
|
108
|
+
def load_ip_rules(
|
|
42
109
|
neo4j_session: neo4j.Session,
|
|
43
|
-
|
|
44
|
-
|
|
110
|
+
data: List[Dict[str, Any]],
|
|
111
|
+
inbound: bool,
|
|
112
|
+
region: str,
|
|
113
|
+
aws_account_id: str,
|
|
45
114
|
update_tag: int,
|
|
46
115
|
) -> None:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
MERGE (group)<-[r:MEMBER_OF_EC2_SECURITY_GROUP]-(rule)
|
|
56
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
57
|
-
SET r.lastupdated = $update_tag;
|
|
58
|
-
""",
|
|
116
|
+
schema = IpPermissionInboundSchema() if inbound else IpRuleSchema()
|
|
117
|
+
load(
|
|
118
|
+
neo4j_session,
|
|
119
|
+
schema,
|
|
120
|
+
data,
|
|
121
|
+
Region=region,
|
|
122
|
+
AWS_ID=aws_account_id,
|
|
123
|
+
lastupdated=update_tag,
|
|
59
124
|
)
|
|
60
125
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
MERGE (rule)<-[r:MEMBER_OF_IP_RULE]-(range)
|
|
79
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
80
|
-
SET r.lastupdated = $update_tag
|
|
81
|
-
"""
|
|
82
|
-
|
|
83
|
-
group_id = group["GroupId"]
|
|
84
|
-
rule_type_map = {
|
|
85
|
-
"IpPermissions": "IpPermissionInbound",
|
|
86
|
-
"IpPermissionsEgress": "IpPermissionEgress",
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if group.get(rule_type):
|
|
90
|
-
for rule in group[rule_type]:
|
|
91
|
-
protocol = rule.get("IpProtocol", "all")
|
|
92
|
-
from_port = rule.get("FromPort")
|
|
93
|
-
to_port = rule.get("ToPort")
|
|
94
|
-
|
|
95
|
-
ruleid = f"{group_id}/{rule_type}/{from_port}{to_port}{protocol}"
|
|
96
|
-
# NOTE Cypher query syntax is incompatible with Python string formatting, so we have to do this awkward
|
|
97
|
-
# NOTE manual formatting instead.
|
|
98
|
-
neo4j_session.run(
|
|
99
|
-
INGEST_RULE_TEMPLATE.safe_substitute(
|
|
100
|
-
rule_label=rule_type_map[rule_type],
|
|
101
|
-
),
|
|
102
|
-
RuleId=ruleid,
|
|
103
|
-
FromPort=from_port,
|
|
104
|
-
ToPort=to_port,
|
|
105
|
-
Protocol=protocol,
|
|
106
|
-
GroupId=group_id,
|
|
107
|
-
update_tag=update_tag,
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
neo4j_session.run(
|
|
111
|
-
ingest_rule_group_pair,
|
|
112
|
-
GroupId=group_id,
|
|
113
|
-
RuleId=ruleid,
|
|
114
|
-
update_tag=update_tag,
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
for ip_range in rule["IpRanges"]:
|
|
118
|
-
range_id = ip_range["CidrIp"]
|
|
119
|
-
neo4j_session.run(
|
|
120
|
-
ingest_range,
|
|
121
|
-
RangeId=range_id,
|
|
122
|
-
RuleId=ruleid,
|
|
123
|
-
update_tag=update_tag,
|
|
124
|
-
)
|
|
126
|
+
|
|
127
|
+
@timeit
|
|
128
|
+
def load_ip_ranges(
|
|
129
|
+
neo4j_session: neo4j.Session,
|
|
130
|
+
data: List[Dict[str, Any]],
|
|
131
|
+
region: str,
|
|
132
|
+
aws_account_id: str,
|
|
133
|
+
update_tag: int,
|
|
134
|
+
) -> None:
|
|
135
|
+
load(
|
|
136
|
+
neo4j_session,
|
|
137
|
+
IpRangeSchema(),
|
|
138
|
+
data,
|
|
139
|
+
Region=region,
|
|
140
|
+
AWS_ID=aws_account_id,
|
|
141
|
+
lastupdated=update_tag,
|
|
142
|
+
)
|
|
125
143
|
|
|
126
144
|
|
|
127
145
|
@timeit
|
|
128
146
|
def load_ec2_security_groupinfo(
|
|
129
147
|
neo4j_session: neo4j.Session,
|
|
130
|
-
data:
|
|
148
|
+
data: Ec2SecurityGroupData,
|
|
131
149
|
region: str,
|
|
132
150
|
current_aws_account_id: str,
|
|
133
151
|
update_tag: int,
|
|
134
152
|
) -> None:
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
144
|
-
SET r.lastupdated = $update_tag
|
|
145
|
-
WITH group
|
|
146
|
-
MATCH (vpc:AWSVpc{id: $VpcId})
|
|
147
|
-
MERGE (vpc)-[rg:MEMBER_OF_EC2_SECURITY_GROUP]->(group)
|
|
148
|
-
ON CREATE SET rg.firstseen = timestamp()
|
|
149
|
-
"""
|
|
150
|
-
|
|
151
|
-
for group in data:
|
|
152
|
-
group_id = group["GroupId"]
|
|
153
|
-
|
|
154
|
-
neo4j_session.run(
|
|
155
|
-
ingest_security_group,
|
|
156
|
-
GroupId=group_id,
|
|
157
|
-
GroupName=group.get("GroupName"),
|
|
158
|
-
Description=group.get("Description"),
|
|
159
|
-
VpcId=group.get("VpcId", None),
|
|
160
|
-
Region=region,
|
|
161
|
-
AWS_ACCOUNT_ID=current_aws_account_id,
|
|
162
|
-
update_tag=update_tag,
|
|
163
|
-
)
|
|
153
|
+
load(
|
|
154
|
+
neo4j_session,
|
|
155
|
+
EC2SecurityGroupSchema(),
|
|
156
|
+
data.groups,
|
|
157
|
+
Region=region,
|
|
158
|
+
AWS_ID=current_aws_account_id,
|
|
159
|
+
lastupdated=update_tag,
|
|
160
|
+
)
|
|
164
161
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
162
|
+
load_ip_rules(
|
|
163
|
+
neo4j_session,
|
|
164
|
+
data.inbound_rules,
|
|
165
|
+
inbound=True,
|
|
166
|
+
region=region,
|
|
167
|
+
aws_account_id=current_aws_account_id,
|
|
168
|
+
update_tag=update_tag,
|
|
169
|
+
)
|
|
170
|
+
load_ip_rules(
|
|
171
|
+
neo4j_session,
|
|
172
|
+
data.egress_rules,
|
|
173
|
+
inbound=False,
|
|
174
|
+
region=region,
|
|
175
|
+
aws_account_id=current_aws_account_id,
|
|
176
|
+
update_tag=update_tag,
|
|
177
|
+
)
|
|
178
|
+
load_ip_ranges(
|
|
179
|
+
neo4j_session,
|
|
180
|
+
data.ranges,
|
|
181
|
+
region,
|
|
182
|
+
current_aws_account_id,
|
|
183
|
+
update_tag,
|
|
184
|
+
)
|
|
172
185
|
|
|
173
186
|
|
|
174
187
|
@timeit
|
|
@@ -176,11 +189,15 @@ def cleanup_ec2_security_groupinfo(
|
|
|
176
189
|
neo4j_session: neo4j.Session,
|
|
177
190
|
common_job_parameters: Dict,
|
|
178
191
|
) -> None:
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
neo4j_session,
|
|
192
|
+
GraphJob.from_node_schema(
|
|
193
|
+
EC2SecurityGroupSchema(),
|
|
182
194
|
common_job_parameters,
|
|
195
|
+
).run(neo4j_session)
|
|
196
|
+
GraphJob.from_node_schema(IpPermissionInboundSchema(), common_job_parameters).run(
|
|
197
|
+
neo4j_session,
|
|
183
198
|
)
|
|
199
|
+
GraphJob.from_node_schema(IpRuleSchema(), common_job_parameters).run(neo4j_session)
|
|
200
|
+
GraphJob.from_node_schema(IpRangeSchema(), common_job_parameters).run(neo4j_session)
|
|
184
201
|
GraphJob.from_node_schema(
|
|
185
202
|
EC2SecurityGroupInstanceSchema(),
|
|
186
203
|
common_job_parameters,
|
|
@@ -203,9 +220,10 @@ def sync_ec2_security_groupinfo(
|
|
|
203
220
|
current_aws_account_id,
|
|
204
221
|
)
|
|
205
222
|
data = get_ec2_security_group_data(boto3_session, region)
|
|
223
|
+
transformed = transform_ec2_security_group_data(data)
|
|
206
224
|
load_ec2_security_groupinfo(
|
|
207
225
|
neo4j_session,
|
|
208
|
-
|
|
226
|
+
transformed,
|
|
209
227
|
region,
|
|
210
228
|
current_aws_account_id,
|
|
211
229
|
update_tag,
|