cartography 0.102.0rc1__py3-none-any.whl → 0.103.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/__main__.py +1 -2
- cartography/_version.py +2 -2
- cartography/cli.py +302 -253
- cartography/client/core/tx.py +39 -18
- cartography/config.py +4 -0
- cartography/driftdetect/__main__.py +1 -2
- cartography/driftdetect/add_shortcut.py +10 -2
- cartography/driftdetect/cli.py +71 -75
- cartography/driftdetect/detect_deviations.py +7 -3
- cartography/driftdetect/get_states.py +20 -8
- cartography/driftdetect/model.py +5 -5
- cartography/driftdetect/serializers.py +8 -6
- cartography/driftdetect/storage.py +2 -2
- cartography/graph/cleanupbuilder.py +35 -15
- cartography/graph/job.py +46 -17
- cartography/graph/querybuilder.py +165 -80
- cartography/graph/statement.py +35 -26
- cartography/intel/analysis.py +4 -1
- cartography/intel/aws/__init__.py +114 -55
- cartography/intel/aws/apigateway.py +134 -63
- cartography/intel/aws/cloudtrail.py +127 -0
- cartography/intel/aws/config.py +56 -20
- cartography/intel/aws/dynamodb.py +108 -40
- cartography/intel/aws/ec2/__init__.py +2 -2
- cartography/intel/aws/ec2/auto_scaling_groups.py +181 -78
- cartography/intel/aws/ec2/elastic_ip_addresses.py +41 -13
- cartography/intel/aws/ec2/images.py +49 -20
- cartography/intel/aws/ec2/instances.py +234 -136
- cartography/intel/aws/ec2/internet_gateways.py +40 -11
- cartography/intel/aws/ec2/key_pairs.py +44 -20
- cartography/intel/aws/ec2/launch_templates.py +101 -59
- cartography/intel/aws/ec2/load_balancer_v2s.py +104 -39
- cartography/intel/aws/ec2/load_balancers.py +82 -42
- cartography/intel/aws/ec2/network_acls.py +89 -65
- cartography/intel/aws/ec2/network_interfaces.py +146 -87
- cartography/intel/aws/ec2/reserved_instances.py +45 -16
- cartography/intel/aws/ec2/route_tables.py +327 -0
- cartography/intel/aws/ec2/security_groups.py +71 -21
- cartography/intel/aws/ec2/snapshots.py +61 -22
- cartography/intel/aws/ec2/subnets.py +54 -18
- cartography/intel/aws/ec2/tgw.py +100 -34
- cartography/intel/aws/ec2/util.py +1 -1
- cartography/intel/aws/ec2/volumes.py +69 -41
- cartography/intel/aws/ec2/vpc.py +37 -12
- cartography/intel/aws/ec2/vpc_peerings.py +83 -24
- cartography/intel/aws/ecr.py +88 -32
- cartography/intel/aws/ecs.py +83 -47
- cartography/intel/aws/eks.py +55 -29
- cartography/intel/aws/elasticache.py +42 -18
- cartography/intel/aws/elasticsearch.py +57 -20
- cartography/intel/aws/emr.py +61 -23
- cartography/intel/aws/iam.py +401 -145
- cartography/intel/aws/iam_instance_profiles.py +22 -22
- cartography/intel/aws/identitycenter.py +71 -37
- cartography/intel/aws/inspector.py +159 -89
- cartography/intel/aws/kms.py +92 -38
- cartography/intel/aws/lambda_function.py +103 -34
- cartography/intel/aws/organizations.py +30 -10
- cartography/intel/aws/permission_relationships.py +133 -51
- cartography/intel/aws/rds.py +249 -85
- cartography/intel/aws/redshift.py +107 -46
- cartography/intel/aws/resourcegroupstaggingapi.py +120 -66
- cartography/intel/aws/resources.py +53 -44
- cartography/intel/aws/route53.py +108 -61
- cartography/intel/aws/s3.py +168 -83
- cartography/intel/aws/s3accountpublicaccessblock.py +157 -0
- cartography/intel/aws/secretsmanager.py +24 -12
- cartography/intel/aws/securityhub.py +20 -9
- cartography/intel/aws/sns.py +166 -0
- cartography/intel/aws/sqs.py +60 -28
- cartography/intel/aws/ssm.py +70 -30
- cartography/intel/aws/util/arns.py +7 -7
- cartography/intel/aws/util/common.py +31 -4
- cartography/intel/azure/__init__.py +78 -19
- cartography/intel/azure/compute.py +101 -27
- cartography/intel/azure/cosmosdb.py +496 -170
- cartography/intel/azure/sql.py +296 -105
- cartography/intel/azure/storage.py +322 -113
- cartography/intel/azure/subscription.py +39 -23
- cartography/intel/azure/tenant.py +13 -4
- cartography/intel/azure/util/credentials.py +95 -55
- cartography/intel/bigfix/__init__.py +2 -2
- cartography/intel/bigfix/computers.py +93 -65
- cartography/intel/create_indexes.py +3 -2
- cartography/intel/crowdstrike/__init__.py +11 -9
- cartography/intel/crowdstrike/endpoints.py +5 -1
- cartography/intel/crowdstrike/spotlight.py +8 -3
- cartography/intel/cve/__init__.py +46 -13
- cartography/intel/cve/feed.py +48 -12
- cartography/intel/digitalocean/__init__.py +22 -13
- cartography/intel/digitalocean/compute.py +75 -108
- cartography/intel/digitalocean/management.py +44 -80
- cartography/intel/digitalocean/platform.py +48 -43
- cartography/intel/dns.py +36 -10
- cartography/intel/duo/__init__.py +21 -16
- cartography/intel/duo/api_host.py +14 -9
- cartography/intel/duo/endpoints.py +50 -45
- cartography/intel/duo/groups.py +18 -14
- cartography/intel/duo/phones.py +37 -34
- cartography/intel/duo/tokens.py +26 -23
- cartography/intel/duo/users.py +54 -50
- cartography/intel/duo/web_authn_credentials.py +30 -25
- cartography/intel/entra/__init__.py +25 -7
- cartography/intel/entra/ou.py +112 -0
- cartography/intel/entra/users.py +69 -63
- cartography/intel/gcp/__init__.py +185 -49
- cartography/intel/gcp/compute.py +418 -231
- cartography/intel/gcp/crm.py +96 -43
- cartography/intel/gcp/dns.py +60 -19
- cartography/intel/gcp/gke.py +72 -38
- cartography/intel/gcp/iam.py +61 -41
- cartography/intel/gcp/storage.py +84 -55
- cartography/intel/github/__init__.py +13 -11
- cartography/intel/github/repos.py +270 -137
- cartography/intel/github/teams.py +170 -88
- cartography/intel/github/users.py +70 -39
- cartography/intel/github/util.py +36 -34
- cartography/intel/gsuite/__init__.py +47 -26
- cartography/intel/gsuite/api.py +73 -30
- cartography/intel/jamf/__init__.py +19 -1
- cartography/intel/jamf/computers.py +30 -7
- cartography/intel/jamf/util.py +7 -2
- cartography/intel/kandji/__init__.py +6 -3
- cartography/intel/kandji/devices.py +14 -8
- cartography/intel/kubernetes/namespaces.py +7 -4
- cartography/intel/kubernetes/pods.py +7 -4
- cartography/intel/kubernetes/services.py +8 -4
- cartography/intel/lastpass/__init__.py +2 -2
- cartography/intel/lastpass/users.py +23 -12
- cartography/intel/oci/__init__.py +44 -11
- cartography/intel/oci/iam.py +134 -38
- cartography/intel/oci/organizations.py +13 -6
- cartography/intel/oci/utils.py +43 -20
- cartography/intel/okta/__init__.py +66 -15
- cartography/intel/okta/applications.py +42 -20
- cartography/intel/okta/awssaml.py +93 -33
- cartography/intel/okta/factors.py +16 -4
- cartography/intel/okta/groups.py +56 -29
- cartography/intel/okta/organization.py +5 -1
- cartography/intel/okta/origins.py +6 -2
- cartography/intel/okta/roles.py +15 -5
- cartography/intel/okta/users.py +20 -8
- cartography/intel/okta/utils.py +6 -4
- cartography/intel/pagerduty/__init__.py +8 -7
- cartography/intel/pagerduty/escalation_policies.py +18 -6
- cartography/intel/pagerduty/schedules.py +12 -4
- cartography/intel/pagerduty/services.py +11 -4
- cartography/intel/pagerduty/teams.py +8 -3
- cartography/intel/pagerduty/users.py +3 -1
- cartography/intel/pagerduty/vendors.py +3 -1
- cartography/intel/semgrep/__init__.py +24 -6
- cartography/intel/semgrep/dependencies.py +50 -28
- cartography/intel/semgrep/deployment.py +3 -1
- cartography/intel/semgrep/findings.py +42 -18
- cartography/intel/snipeit/__init__.py +17 -3
- cartography/intel/snipeit/asset.py +12 -6
- cartography/intel/snipeit/user.py +8 -5
- cartography/intel/snipeit/util.py +9 -4
- cartography/models/aws/apigateway.py +21 -17
- cartography/models/aws/apigatewaycertificate.py +28 -22
- cartography/models/aws/apigatewayresource.py +28 -20
- cartography/models/aws/apigatewaystage.py +33 -25
- cartography/models/aws/cloudtrail/__init__.py +0 -0
- cartography/models/aws/cloudtrail/trail.py +61 -0
- cartography/models/aws/dynamodb/gsi.py +30 -22
- cartography/models/aws/dynamodb/tables.py +25 -17
- cartography/models/aws/ec2/auto_scaling_groups.py +102 -82
- cartography/models/aws/ec2/images.py +36 -34
- cartography/models/aws/ec2/instances.py +51 -45
- cartography/models/aws/ec2/keypair.py +21 -16
- cartography/models/aws/ec2/keypair_instance.py +28 -21
- cartography/models/aws/ec2/launch_configurations.py +30 -26
- cartography/models/aws/ec2/launch_template_versions.py +48 -38
- cartography/models/aws/ec2/launch_templates.py +21 -17
- cartography/models/aws/ec2/load_balancer_listeners.py +27 -23
- cartography/models/aws/ec2/load_balancers.py +47 -37
- cartography/models/aws/ec2/network_acl_rules.py +38 -30
- cartography/models/aws/ec2/network_acls.py +38 -29
- cartography/models/aws/ec2/networkinterface_instance.py +52 -39
- cartography/models/aws/ec2/networkinterfaces.py +53 -37
- cartography/models/aws/ec2/privateip_networkinterface.py +32 -22
- cartography/models/aws/ec2/reservations.py +18 -14
- cartography/models/aws/ec2/route_table_associations.py +97 -0
- cartography/models/aws/ec2/route_tables.py +128 -0
- cartography/models/aws/ec2/routes.py +85 -0
- cartography/models/aws/ec2/securitygroup_instance.py +29 -20
- cartography/models/aws/ec2/securitygroup_networkinterface.py +24 -15
- cartography/models/aws/ec2/subnet_instance.py +24 -19
- cartography/models/aws/ec2/subnet_networkinterface.py +40 -31
- cartography/models/aws/ec2/volumes.py +47 -40
- cartography/models/aws/eks/clusters.py +23 -21
- cartography/models/aws/emr.py +32 -30
- cartography/models/aws/iam/instanceprofile.py +33 -24
- cartography/models/aws/identitycenter/awsidentitycenter.py +18 -14
- cartography/models/aws/identitycenter/awspermissionset.py +37 -29
- cartography/models/aws/identitycenter/awsssouser.py +23 -21
- cartography/models/aws/inspector/findings.py +77 -65
- cartography/models/aws/inspector/packages.py +35 -29
- cartography/models/aws/s3/__init__.py +0 -0
- cartography/models/aws/s3/account_public_access_block.py +51 -0
- cartography/models/aws/sns/__init__.py +0 -0
- cartography/models/aws/sns/topic.py +50 -0
- cartography/models/aws/ssm/instance_information.py +51 -39
- cartography/models/aws/ssm/instance_patch.py +32 -26
- cartography/models/bigfix/bigfix_computer.py +42 -38
- cartography/models/bigfix/bigfix_root.py +3 -3
- cartography/models/core/common.py +12 -10
- cartography/models/core/nodes.py +5 -2
- cartography/models/core/relationships.py +14 -6
- cartography/models/crowdstrike/hosts.py +37 -35
- cartography/models/cve/cve.py +34 -32
- cartography/models/cve/cve_feed.py +6 -6
- cartography/models/digitalocean/__init__.py +0 -0
- cartography/models/digitalocean/account.py +21 -0
- cartography/models/digitalocean/droplet.py +56 -0
- cartography/models/digitalocean/project.py +48 -0
- cartography/models/duo/api_host.py +3 -3
- cartography/models/duo/endpoint.py +43 -41
- cartography/models/duo/group.py +14 -14
- cartography/models/duo/phone.py +27 -27
- cartography/models/duo/token.py +16 -16
- cartography/models/duo/user.py +46 -44
- cartography/models/duo/web_authn_credential.py +27 -19
- cartography/models/entra/ou.py +48 -0
- cartography/models/entra/tenant.py +24 -18
- cartography/models/entra/user.py +64 -48
- cartography/models/gcp/iam.py +23 -23
- cartography/models/github/orgs.py +5 -4
- cartography/models/github/teams.py +37 -31
- cartography/models/github/users.py +34 -23
- cartography/models/kandji/device.py +22 -16
- cartography/models/kandji/tenant.py +6 -4
- cartography/models/lastpass/tenant.py +3 -3
- cartography/models/lastpass/user.py +32 -28
- cartography/models/semgrep/dependencies.py +36 -24
- cartography/models/semgrep/deployment.py +5 -5
- cartography/models/semgrep/findings.py +58 -42
- cartography/models/semgrep/locations.py +27 -21
- cartography/models/snipeit/asset.py +30 -21
- cartography/models/snipeit/tenant.py +6 -4
- cartography/models/snipeit/user.py +19 -12
- cartography/stats.py +3 -3
- cartography/sync.py +107 -31
- cartography/util.py +84 -62
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/METADATA +3 -14
- cartography-0.103.0rc1.dist-info/RECORD +396 -0
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/WHEEL +1 -1
- cartography-0.102.0rc1.dist-info/RECORD +0 -377
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/entry_points.txt +0 -0
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/top_level.txt +0 -0
cartography/intel/aws/rds.py
CHANGED
|
@@ -20,22 +20,28 @@ stat_handler = get_stats_client(__name__)
|
|
|
20
20
|
|
|
21
21
|
@timeit
|
|
22
22
|
@aws_handle_regions
|
|
23
|
-
def get_rds_cluster_data(
|
|
23
|
+
def get_rds_cluster_data(
|
|
24
|
+
boto3_session: boto3.session.Session,
|
|
25
|
+
region: str,
|
|
26
|
+
) -> List[Any]:
|
|
24
27
|
"""
|
|
25
28
|
Create an RDS boto3 client and grab all the DBClusters.
|
|
26
29
|
"""
|
|
27
|
-
client = boto3_session.client(
|
|
28
|
-
paginator = client.get_paginator(
|
|
30
|
+
client = boto3_session.client("rds", region_name=region)
|
|
31
|
+
paginator = client.get_paginator("describe_db_clusters")
|
|
29
32
|
instances: List[Any] = []
|
|
30
33
|
for page in paginator.paginate():
|
|
31
|
-
instances.extend(page[
|
|
34
|
+
instances.extend(page["DBClusters"])
|
|
32
35
|
|
|
33
36
|
return instances
|
|
34
37
|
|
|
35
38
|
|
|
36
39
|
@timeit
|
|
37
40
|
def load_rds_clusters(
|
|
38
|
-
neo4j_session: neo4j.Session,
|
|
41
|
+
neo4j_session: neo4j.Session,
|
|
42
|
+
data: Dict,
|
|
43
|
+
region: str,
|
|
44
|
+
current_aws_account_id: str,
|
|
39
45
|
aws_update_tag: int,
|
|
40
46
|
) -> None:
|
|
41
47
|
"""
|
|
@@ -94,13 +100,31 @@ def load_rds_clusters(
|
|
|
94
100
|
# TODO: track security groups
|
|
95
101
|
# TODO: track subnet groups
|
|
96
102
|
|
|
97
|
-
cluster[
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
cluster[
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
cluster["EarliestRestorableTime"] = dict_value_to_str(
|
|
104
|
+
cluster,
|
|
105
|
+
"EarliestRestorableTime",
|
|
106
|
+
)
|
|
107
|
+
cluster["LatestRestorableTime"] = dict_value_to_str(
|
|
108
|
+
cluster,
|
|
109
|
+
"LatestRestorableTime",
|
|
110
|
+
)
|
|
111
|
+
cluster["ClusterCreateTime"] = dict_value_to_str(cluster, "ClusterCreateTime")
|
|
112
|
+
cluster["EarliestBacktrackTime"] = dict_value_to_str(
|
|
113
|
+
cluster,
|
|
114
|
+
"EarliestBacktrackTime",
|
|
115
|
+
)
|
|
116
|
+
cluster["ScalingConfigurationInfoMinCapacity"] = cluster.get(
|
|
117
|
+
"ScalingConfigurationInfo",
|
|
118
|
+
{},
|
|
119
|
+
).get("MinCapacity")
|
|
120
|
+
cluster["ScalingConfigurationInfoMaxCapacity"] = cluster.get(
|
|
121
|
+
"ScalingConfigurationInfo",
|
|
122
|
+
{},
|
|
123
|
+
).get("MaxCapacity")
|
|
124
|
+
cluster["ScalingConfigurationInfoAutoPause"] = cluster.get(
|
|
125
|
+
"ScalingConfigurationInfo",
|
|
126
|
+
{},
|
|
127
|
+
).get("AutoPause")
|
|
104
128
|
|
|
105
129
|
neo4j_session.run(
|
|
106
130
|
ingest_rds_cluster,
|
|
@@ -113,22 +137,28 @@ def load_rds_clusters(
|
|
|
113
137
|
|
|
114
138
|
@timeit
|
|
115
139
|
@aws_handle_regions
|
|
116
|
-
def get_rds_instance_data(
|
|
140
|
+
def get_rds_instance_data(
|
|
141
|
+
boto3_session: boto3.session.Session,
|
|
142
|
+
region: str,
|
|
143
|
+
) -> List[Any]:
|
|
117
144
|
"""
|
|
118
145
|
Create an RDS boto3 client and grab all the DBInstances.
|
|
119
146
|
"""
|
|
120
|
-
client = boto3_session.client(
|
|
121
|
-
paginator = client.get_paginator(
|
|
147
|
+
client = boto3_session.client("rds", region_name=region)
|
|
148
|
+
paginator = client.get_paginator("describe_db_instances")
|
|
122
149
|
instances: List[Any] = []
|
|
123
150
|
for page in paginator.paginate():
|
|
124
|
-
instances.extend(page[
|
|
151
|
+
instances.extend(page["DBInstances"])
|
|
125
152
|
|
|
126
153
|
return instances
|
|
127
154
|
|
|
128
155
|
|
|
129
156
|
@timeit
|
|
130
157
|
def load_rds_instances(
|
|
131
|
-
neo4j_session: neo4j.Session,
|
|
158
|
+
neo4j_session: neo4j.Session,
|
|
159
|
+
data: Dict,
|
|
160
|
+
region: str,
|
|
161
|
+
current_aws_account_id: str,
|
|
132
162
|
aws_update_tag: int,
|
|
133
163
|
) -> None:
|
|
134
164
|
"""
|
|
@@ -192,17 +222,17 @@ def load_rds_instances(
|
|
|
192
222
|
if rds.get("DBClusterIdentifier"):
|
|
193
223
|
clusters.append(rds)
|
|
194
224
|
|
|
195
|
-
if rds.get(
|
|
225
|
+
if rds.get("VpcSecurityGroups"):
|
|
196
226
|
secgroups.append(rds)
|
|
197
227
|
|
|
198
|
-
if rds.get(
|
|
228
|
+
if rds.get("DBSubnetGroup"):
|
|
199
229
|
subnets.append(rds)
|
|
200
230
|
|
|
201
|
-
rds[
|
|
202
|
-
rds[
|
|
203
|
-
rds[
|
|
204
|
-
rds[
|
|
205
|
-
rds[
|
|
231
|
+
rds["InstanceCreateTime"] = dict_value_to_str(rds, "InstanceCreateTime")
|
|
232
|
+
rds["LatestRestorableTime"] = dict_value_to_str(rds, "LatestRestorableTime")
|
|
233
|
+
rds["EndpointAddress"] = ep.get("Address")
|
|
234
|
+
rds["EndpointHostedZoneId"] = ep.get("HostedZoneId")
|
|
235
|
+
rds["EndpointPort"] = ep.get("Port")
|
|
206
236
|
|
|
207
237
|
neo4j_session.run(
|
|
208
238
|
ingest_rds_instance,
|
|
@@ -212,24 +242,36 @@ def load_rds_instances(
|
|
|
212
242
|
aws_update_tag=aws_update_tag,
|
|
213
243
|
)
|
|
214
244
|
_attach_ec2_security_groups(neo4j_session, secgroups, aws_update_tag)
|
|
215
|
-
_attach_ec2_subnet_groups(
|
|
245
|
+
_attach_ec2_subnet_groups(
|
|
246
|
+
neo4j_session,
|
|
247
|
+
subnets,
|
|
248
|
+
region,
|
|
249
|
+
current_aws_account_id,
|
|
250
|
+
aws_update_tag,
|
|
251
|
+
)
|
|
216
252
|
_attach_read_replicas(neo4j_session, read_replicas, aws_update_tag)
|
|
217
253
|
_attach_clusters(neo4j_session, clusters, aws_update_tag)
|
|
218
254
|
|
|
219
255
|
|
|
220
256
|
@timeit
|
|
221
257
|
@aws_handle_regions
|
|
222
|
-
def get_rds_snapshot_data(
|
|
258
|
+
def get_rds_snapshot_data(
|
|
259
|
+
boto3_session: boto3.session.Session,
|
|
260
|
+
region: str,
|
|
261
|
+
) -> List[Any]:
|
|
223
262
|
"""
|
|
224
263
|
Create an RDS boto3 client and grab all the DBSnapshots.
|
|
225
264
|
"""
|
|
226
|
-
client = boto3_session.client(
|
|
227
|
-
return aws_paginate(client,
|
|
265
|
+
client = boto3_session.client("rds", region_name=region)
|
|
266
|
+
return aws_paginate(client, "describe_db_snapshots", "DBSnapshots")
|
|
228
267
|
|
|
229
268
|
|
|
230
269
|
@timeit
|
|
231
270
|
def load_rds_snapshots(
|
|
232
|
-
neo4j_session: neo4j.Session,
|
|
271
|
+
neo4j_session: neo4j.Session,
|
|
272
|
+
data: Dict,
|
|
273
|
+
region: str,
|
|
274
|
+
current_aws_account_id: str,
|
|
233
275
|
aws_update_tag: int,
|
|
234
276
|
) -> None:
|
|
235
277
|
"""
|
|
@@ -293,7 +335,11 @@ def load_rds_snapshots(
|
|
|
293
335
|
|
|
294
336
|
|
|
295
337
|
@timeit
|
|
296
|
-
def _attach_snapshots(
|
|
338
|
+
def _attach_snapshots(
|
|
339
|
+
neo4j_session: neo4j.Session,
|
|
340
|
+
snapshots: List[Dict],
|
|
341
|
+
aws_update_tag: int,
|
|
342
|
+
) -> None:
|
|
297
343
|
"""
|
|
298
344
|
Attach snapshots to their source instance
|
|
299
345
|
"""
|
|
@@ -314,7 +360,10 @@ def _attach_snapshots(neo4j_session: neo4j.Session, snapshots: List[Dict], aws_u
|
|
|
314
360
|
|
|
315
361
|
@timeit
|
|
316
362
|
def _attach_ec2_subnet_groups(
|
|
317
|
-
neo4j_session: neo4j.Session,
|
|
363
|
+
neo4j_session: neo4j.Session,
|
|
364
|
+
instances: List[Dict],
|
|
365
|
+
region: str,
|
|
366
|
+
current_aws_account_id: str,
|
|
318
367
|
aws_update_tag: int,
|
|
319
368
|
) -> None:
|
|
320
369
|
"""
|
|
@@ -337,22 +386,35 @@ def _attach_ec2_subnet_groups(
|
|
|
337
386
|
"""
|
|
338
387
|
db_sngs = []
|
|
339
388
|
for instance in instances:
|
|
340
|
-
db_sng = instance[
|
|
341
|
-
db_sng[
|
|
342
|
-
|
|
389
|
+
db_sng = instance["DBSubnetGroup"]
|
|
390
|
+
db_sng["arn"] = _get_db_subnet_group_arn(
|
|
391
|
+
region,
|
|
392
|
+
current_aws_account_id,
|
|
393
|
+
db_sng["DBSubnetGroupName"],
|
|
394
|
+
)
|
|
395
|
+
db_sng["instance_arn"] = instance["DBInstanceArn"]
|
|
343
396
|
db_sngs.append(db_sng)
|
|
344
397
|
neo4j_session.run(
|
|
345
398
|
attach_rds_to_subnet_group,
|
|
346
399
|
SubnetGroups=db_sngs,
|
|
347
400
|
aws_update_tag=aws_update_tag,
|
|
348
401
|
)
|
|
349
|
-
_attach_ec2_subnets_to_subnetgroup(
|
|
402
|
+
_attach_ec2_subnets_to_subnetgroup(
|
|
403
|
+
neo4j_session,
|
|
404
|
+
db_sngs,
|
|
405
|
+
region,
|
|
406
|
+
current_aws_account_id,
|
|
407
|
+
aws_update_tag,
|
|
408
|
+
)
|
|
350
409
|
|
|
351
410
|
|
|
352
411
|
@timeit
|
|
353
412
|
def _attach_ec2_subnets_to_subnetgroup(
|
|
354
|
-
neo4j_session: neo4j.Session,
|
|
355
|
-
|
|
413
|
+
neo4j_session: neo4j.Session,
|
|
414
|
+
db_subnet_groups: List[Dict],
|
|
415
|
+
region: str,
|
|
416
|
+
current_aws_account_id: str,
|
|
417
|
+
aws_update_tag: int,
|
|
356
418
|
) -> None:
|
|
357
419
|
"""
|
|
358
420
|
Attach EC2Subnets to their DB Subnet Group.
|
|
@@ -375,15 +437,21 @@ def _attach_ec2_subnets_to_subnetgroup(
|
|
|
375
437
|
"""
|
|
376
438
|
subnets = []
|
|
377
439
|
for subnet_group in db_subnet_groups:
|
|
378
|
-
for subnet in subnet_group.get(
|
|
379
|
-
sn_id = subnet.get(
|
|
380
|
-
sng_arn = _get_db_subnet_group_arn(
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
440
|
+
for subnet in subnet_group.get("Subnets", []):
|
|
441
|
+
sn_id = subnet.get("SubnetIdentifier")
|
|
442
|
+
sng_arn = _get_db_subnet_group_arn(
|
|
443
|
+
region,
|
|
444
|
+
current_aws_account_id,
|
|
445
|
+
subnet_group["DBSubnetGroupName"],
|
|
446
|
+
)
|
|
447
|
+
az = subnet.get("SubnetAvailabilityZone", {}).get("Name")
|
|
448
|
+
subnets.append(
|
|
449
|
+
{
|
|
450
|
+
"sn_id": sn_id,
|
|
451
|
+
"sng_arn": sng_arn,
|
|
452
|
+
"az": az,
|
|
453
|
+
},
|
|
454
|
+
)
|
|
387
455
|
neo4j_session.run(
|
|
388
456
|
attach_subnets_to_sng,
|
|
389
457
|
Subnets=subnets,
|
|
@@ -392,7 +460,11 @@ def _attach_ec2_subnets_to_subnetgroup(
|
|
|
392
460
|
|
|
393
461
|
|
|
394
462
|
@timeit
|
|
395
|
-
def _attach_ec2_security_groups(
|
|
463
|
+
def _attach_ec2_security_groups(
|
|
464
|
+
neo4j_session: neo4j.Session,
|
|
465
|
+
instances: List[Dict],
|
|
466
|
+
aws_update_tag: int,
|
|
467
|
+
) -> None:
|
|
396
468
|
"""
|
|
397
469
|
Attach an RDS instance to its EC2SecurityGroups
|
|
398
470
|
"""
|
|
@@ -406,11 +478,13 @@ def _attach_ec2_security_groups(neo4j_session: neo4j.Session, instances: List[Di
|
|
|
406
478
|
"""
|
|
407
479
|
groups = []
|
|
408
480
|
for instance in instances:
|
|
409
|
-
for group in instance[
|
|
410
|
-
groups.append(
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
481
|
+
for group in instance["VpcSecurityGroups"]:
|
|
482
|
+
groups.append(
|
|
483
|
+
{
|
|
484
|
+
"arn": instance["DBInstanceArn"],
|
|
485
|
+
"group_id": group["VpcSecurityGroupId"],
|
|
486
|
+
},
|
|
487
|
+
)
|
|
414
488
|
neo4j_session.run(
|
|
415
489
|
attach_rds_to_group,
|
|
416
490
|
Groups=groups,
|
|
@@ -419,7 +493,11 @@ def _attach_ec2_security_groups(neo4j_session: neo4j.Session, instances: List[Di
|
|
|
419
493
|
|
|
420
494
|
|
|
421
495
|
@timeit
|
|
422
|
-
def _attach_read_replicas(
|
|
496
|
+
def _attach_read_replicas(
|
|
497
|
+
neo4j_session: neo4j.Session,
|
|
498
|
+
read_replicas: List[Dict],
|
|
499
|
+
aws_update_tag: int,
|
|
500
|
+
) -> None:
|
|
423
501
|
"""
|
|
424
502
|
Attach read replicas to their source instances
|
|
425
503
|
"""
|
|
@@ -439,7 +517,11 @@ def _attach_read_replicas(neo4j_session: neo4j.Session, read_replicas: List[Dict
|
|
|
439
517
|
|
|
440
518
|
|
|
441
519
|
@timeit
|
|
442
|
-
def _attach_clusters(
|
|
520
|
+
def _attach_clusters(
|
|
521
|
+
neo4j_session: neo4j.Session,
|
|
522
|
+
cluster_members: List[Dict],
|
|
523
|
+
aws_update_tag: int,
|
|
524
|
+
) -> None:
|
|
443
525
|
"""
|
|
444
526
|
Attach cluster members to their source clusters
|
|
445
527
|
"""
|
|
@@ -462,13 +544,20 @@ def _validate_rds_endpoint(rds: Dict) -> Dict:
|
|
|
462
544
|
"""
|
|
463
545
|
Get Endpoint from RDS data structure. Log to debug if an Endpoint field does not exist.
|
|
464
546
|
"""
|
|
465
|
-
ep = rds.get(
|
|
547
|
+
ep = rds.get("Endpoint", {})
|
|
466
548
|
if not ep:
|
|
467
|
-
logger.debug(
|
|
549
|
+
logger.debug(
|
|
550
|
+
"RDS instance does not have an Endpoint field. Here is the object: %r",
|
|
551
|
+
rds,
|
|
552
|
+
)
|
|
468
553
|
return ep
|
|
469
554
|
|
|
470
555
|
|
|
471
|
-
def _get_db_subnet_group_arn(
|
|
556
|
+
def _get_db_subnet_group_arn(
|
|
557
|
+
region: str,
|
|
558
|
+
current_aws_account_id: str,
|
|
559
|
+
db_subnet_group_name: str,
|
|
560
|
+
) -> str:
|
|
472
561
|
"""
|
|
473
562
|
Return an ARN for the DB subnet group name by concatenating the account name and region.
|
|
474
563
|
This is done to avoid another AWS API call since the describe_db_instances boto call does not return the DB subnet
|
|
@@ -476,7 +565,9 @@ def _get_db_subnet_group_arn(region: str, current_aws_account_id: str, db_subnet
|
|
|
476
565
|
Form is arn:aws:rds:{region}:{account-id}:subgrp:{subnet-group-name}
|
|
477
566
|
as per https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html
|
|
478
567
|
"""
|
|
479
|
-
return
|
|
568
|
+
return (
|
|
569
|
+
f"arn:aws:rds:{region}:{current_aws_account_id}:subgrp:{db_subnet_group_name}"
|
|
570
|
+
)
|
|
480
571
|
|
|
481
572
|
|
|
482
573
|
@timeit
|
|
@@ -486,49 +577,90 @@ def transform_rds_snapshots(data: Dict) -> List[Dict]:
|
|
|
486
577
|
for snapshot in data:
|
|
487
578
|
snapshots.append(snapshot)
|
|
488
579
|
|
|
489
|
-
snapshot[
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
snapshot[
|
|
580
|
+
snapshot["SnapshotCreateTime"] = dict_value_to_str(
|
|
581
|
+
snapshot,
|
|
582
|
+
"EarliestRestorableTime",
|
|
583
|
+
)
|
|
584
|
+
snapshot["InstanceCreateTime"] = dict_value_to_str(
|
|
585
|
+
snapshot,
|
|
586
|
+
"InstanceCreateTime",
|
|
587
|
+
)
|
|
588
|
+
snapshot["ProcessorFeatures"] = dict_value_to_str(snapshot, "ProcessorFeatures")
|
|
589
|
+
snapshot["OriginalSnapshotCreateTime"] = dict_value_to_str(
|
|
590
|
+
snapshot,
|
|
591
|
+
"OriginalSnapshotCreateTime",
|
|
592
|
+
)
|
|
593
|
+
snapshot["SnapshotDatabaseTime"] = dict_value_to_str(
|
|
594
|
+
snapshot,
|
|
595
|
+
"SnapshotDatabaseTime",
|
|
596
|
+
)
|
|
494
597
|
|
|
495
598
|
return snapshots
|
|
496
599
|
|
|
497
600
|
|
|
498
601
|
@timeit
|
|
499
|
-
def cleanup_rds_instances_and_db_subnet_groups(
|
|
602
|
+
def cleanup_rds_instances_and_db_subnet_groups(
|
|
603
|
+
neo4j_session: neo4j.Session,
|
|
604
|
+
common_job_parameters: Dict,
|
|
605
|
+
) -> None:
|
|
500
606
|
"""
|
|
501
607
|
Remove RDS graph nodes and DBSubnetGroups that were created from other ingestion runs
|
|
502
608
|
"""
|
|
503
|
-
run_cleanup_job(
|
|
609
|
+
run_cleanup_job(
|
|
610
|
+
"aws_import_rds_instances_cleanup.json",
|
|
611
|
+
neo4j_session,
|
|
612
|
+
common_job_parameters,
|
|
613
|
+
)
|
|
504
614
|
|
|
505
615
|
|
|
506
616
|
@timeit
|
|
507
|
-
def cleanup_rds_clusters(
|
|
617
|
+
def cleanup_rds_clusters(
|
|
618
|
+
neo4j_session: neo4j.Session,
|
|
619
|
+
common_job_parameters: Dict,
|
|
620
|
+
) -> None:
|
|
508
621
|
"""
|
|
509
622
|
Remove RDS cluster graph nodes
|
|
510
623
|
"""
|
|
511
|
-
run_cleanup_job(
|
|
624
|
+
run_cleanup_job(
|
|
625
|
+
"aws_import_rds_clusters_cleanup.json",
|
|
626
|
+
neo4j_session,
|
|
627
|
+
common_job_parameters,
|
|
628
|
+
)
|
|
512
629
|
|
|
513
630
|
|
|
514
631
|
@timeit
|
|
515
|
-
def cleanup_rds_snapshots(
|
|
632
|
+
def cleanup_rds_snapshots(
|
|
633
|
+
neo4j_session: neo4j.Session,
|
|
634
|
+
common_job_parameters: Dict,
|
|
635
|
+
) -> None:
|
|
516
636
|
"""
|
|
517
637
|
Remove RDS snapshots graph nodes
|
|
518
638
|
"""
|
|
519
|
-
run_cleanup_job(
|
|
639
|
+
run_cleanup_job(
|
|
640
|
+
"aws_import_rds_snapshots_cleanup.json",
|
|
641
|
+
neo4j_session,
|
|
642
|
+
common_job_parameters,
|
|
643
|
+
)
|
|
520
644
|
|
|
521
645
|
|
|
522
646
|
@timeit
|
|
523
647
|
def sync_rds_clusters(
|
|
524
|
-
neo4j_session: neo4j.Session,
|
|
525
|
-
|
|
648
|
+
neo4j_session: neo4j.Session,
|
|
649
|
+
boto3_session: boto3.session.Session,
|
|
650
|
+
regions: List[str],
|
|
651
|
+
current_aws_account_id: str,
|
|
652
|
+
update_tag: int,
|
|
653
|
+
common_job_parameters: Dict,
|
|
526
654
|
) -> None:
|
|
527
655
|
"""
|
|
528
656
|
Grab RDS instance data from AWS, ingest to neo4j, and run the cleanup job.
|
|
529
657
|
"""
|
|
530
658
|
for region in regions:
|
|
531
|
-
logger.info(
|
|
659
|
+
logger.info(
|
|
660
|
+
"Syncing RDS for region '%s' in account '%s'.",
|
|
661
|
+
region,
|
|
662
|
+
current_aws_account_id,
|
|
663
|
+
)
|
|
532
664
|
data = get_rds_cluster_data(boto3_session, region)
|
|
533
665
|
load_rds_clusters(neo4j_session, data, region, current_aws_account_id, update_tag) # type: ignore
|
|
534
666
|
cleanup_rds_clusters(neo4j_session, common_job_parameters)
|
|
@@ -536,14 +668,22 @@ def sync_rds_clusters(
|
|
|
536
668
|
|
|
537
669
|
@timeit
|
|
538
670
|
def sync_rds_instances(
|
|
539
|
-
neo4j_session: neo4j.Session,
|
|
540
|
-
|
|
671
|
+
neo4j_session: neo4j.Session,
|
|
672
|
+
boto3_session: boto3.session.Session,
|
|
673
|
+
regions: List[str],
|
|
674
|
+
current_aws_account_id: str,
|
|
675
|
+
update_tag: int,
|
|
676
|
+
common_job_parameters: Dict,
|
|
541
677
|
) -> None:
|
|
542
678
|
"""
|
|
543
679
|
Grab RDS instance data from AWS, ingest to neo4j, and run the cleanup job.
|
|
544
680
|
"""
|
|
545
681
|
for region in regions:
|
|
546
|
-
logger.info(
|
|
682
|
+
logger.info(
|
|
683
|
+
"Syncing RDS for region '%s' in account '%s'.",
|
|
684
|
+
region,
|
|
685
|
+
current_aws_account_id,
|
|
686
|
+
)
|
|
547
687
|
data = get_rds_instance_data(boto3_session, region)
|
|
548
688
|
load_rds_instances(neo4j_session, data, region, current_aws_account_id, update_tag) # type: ignore
|
|
549
689
|
cleanup_rds_instances_and_db_subnet_groups(neo4j_session, common_job_parameters)
|
|
@@ -551,14 +691,22 @@ def sync_rds_instances(
|
|
|
551
691
|
|
|
552
692
|
@timeit
|
|
553
693
|
def sync_rds_snapshots(
|
|
554
|
-
neo4j_session: neo4j.Session,
|
|
555
|
-
|
|
694
|
+
neo4j_session: neo4j.Session,
|
|
695
|
+
boto3_session: boto3.session.Session,
|
|
696
|
+
regions: List[str],
|
|
697
|
+
current_aws_account_id: str,
|
|
698
|
+
update_tag: int,
|
|
699
|
+
common_job_parameters: Dict,
|
|
556
700
|
) -> None:
|
|
557
701
|
"""
|
|
558
702
|
Grab RDS snapshot data from AWS, ingest to neo4j, and run the cleanup job.
|
|
559
703
|
"""
|
|
560
704
|
for region in regions:
|
|
561
|
-
logger.info(
|
|
705
|
+
logger.info(
|
|
706
|
+
"Syncing RDS for region '%s' in account '%s'.",
|
|
707
|
+
region,
|
|
708
|
+
current_aws_account_id,
|
|
709
|
+
)
|
|
562
710
|
data = get_rds_snapshot_data(boto3_session, region)
|
|
563
711
|
load_rds_snapshots(neo4j_session, data, region, current_aws_account_id, update_tag) # type: ignore
|
|
564
712
|
cleanup_rds_snapshots(neo4j_session, common_job_parameters)
|
|
@@ -566,26 +714,42 @@ def sync_rds_snapshots(
|
|
|
566
714
|
|
|
567
715
|
@timeit
|
|
568
716
|
def sync(
|
|
569
|
-
neo4j_session: neo4j.Session,
|
|
570
|
-
|
|
717
|
+
neo4j_session: neo4j.Session,
|
|
718
|
+
boto3_session: boto3.session.Session,
|
|
719
|
+
regions: List[str],
|
|
720
|
+
current_aws_account_id: str,
|
|
721
|
+
update_tag: int,
|
|
722
|
+
common_job_parameters: Dict,
|
|
571
723
|
) -> None:
|
|
572
724
|
sync_rds_clusters(
|
|
573
|
-
neo4j_session,
|
|
725
|
+
neo4j_session,
|
|
726
|
+
boto3_session,
|
|
727
|
+
regions,
|
|
728
|
+
current_aws_account_id,
|
|
729
|
+
update_tag,
|
|
574
730
|
common_job_parameters,
|
|
575
731
|
)
|
|
576
732
|
sync_rds_instances(
|
|
577
|
-
neo4j_session,
|
|
733
|
+
neo4j_session,
|
|
734
|
+
boto3_session,
|
|
735
|
+
regions,
|
|
736
|
+
current_aws_account_id,
|
|
737
|
+
update_tag,
|
|
578
738
|
common_job_parameters,
|
|
579
739
|
)
|
|
580
740
|
sync_rds_snapshots(
|
|
581
|
-
neo4j_session,
|
|
741
|
+
neo4j_session,
|
|
742
|
+
boto3_session,
|
|
743
|
+
regions,
|
|
744
|
+
current_aws_account_id,
|
|
745
|
+
update_tag,
|
|
582
746
|
common_job_parameters,
|
|
583
747
|
)
|
|
584
748
|
merge_module_sync_metadata(
|
|
585
749
|
neo4j_session,
|
|
586
|
-
group_type=
|
|
750
|
+
group_type="AWSAccount",
|
|
587
751
|
group_id=current_aws_account_id,
|
|
588
|
-
synced_type=
|
|
752
|
+
synced_type="RDSCluster",
|
|
589
753
|
update_tag=update_tag,
|
|
590
754
|
stat_handler=stat_handler,
|
|
591
755
|
)
|