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.

Files changed (251) hide show
  1. cartography/__main__.py +1 -2
  2. cartography/_version.py +2 -2
  3. cartography/cli.py +302 -253
  4. cartography/client/core/tx.py +39 -18
  5. cartography/config.py +4 -0
  6. cartography/driftdetect/__main__.py +1 -2
  7. cartography/driftdetect/add_shortcut.py +10 -2
  8. cartography/driftdetect/cli.py +71 -75
  9. cartography/driftdetect/detect_deviations.py +7 -3
  10. cartography/driftdetect/get_states.py +20 -8
  11. cartography/driftdetect/model.py +5 -5
  12. cartography/driftdetect/serializers.py +8 -6
  13. cartography/driftdetect/storage.py +2 -2
  14. cartography/graph/cleanupbuilder.py +35 -15
  15. cartography/graph/job.py +46 -17
  16. cartography/graph/querybuilder.py +165 -80
  17. cartography/graph/statement.py +35 -26
  18. cartography/intel/analysis.py +4 -1
  19. cartography/intel/aws/__init__.py +114 -55
  20. cartography/intel/aws/apigateway.py +134 -63
  21. cartography/intel/aws/cloudtrail.py +127 -0
  22. cartography/intel/aws/config.py +56 -20
  23. cartography/intel/aws/dynamodb.py +108 -40
  24. cartography/intel/aws/ec2/__init__.py +2 -2
  25. cartography/intel/aws/ec2/auto_scaling_groups.py +181 -78
  26. cartography/intel/aws/ec2/elastic_ip_addresses.py +41 -13
  27. cartography/intel/aws/ec2/images.py +49 -20
  28. cartography/intel/aws/ec2/instances.py +234 -136
  29. cartography/intel/aws/ec2/internet_gateways.py +40 -11
  30. cartography/intel/aws/ec2/key_pairs.py +44 -20
  31. cartography/intel/aws/ec2/launch_templates.py +101 -59
  32. cartography/intel/aws/ec2/load_balancer_v2s.py +104 -39
  33. cartography/intel/aws/ec2/load_balancers.py +82 -42
  34. cartography/intel/aws/ec2/network_acls.py +89 -65
  35. cartography/intel/aws/ec2/network_interfaces.py +146 -87
  36. cartography/intel/aws/ec2/reserved_instances.py +45 -16
  37. cartography/intel/aws/ec2/route_tables.py +327 -0
  38. cartography/intel/aws/ec2/security_groups.py +71 -21
  39. cartography/intel/aws/ec2/snapshots.py +61 -22
  40. cartography/intel/aws/ec2/subnets.py +54 -18
  41. cartography/intel/aws/ec2/tgw.py +100 -34
  42. cartography/intel/aws/ec2/util.py +1 -1
  43. cartography/intel/aws/ec2/volumes.py +69 -41
  44. cartography/intel/aws/ec2/vpc.py +37 -12
  45. cartography/intel/aws/ec2/vpc_peerings.py +83 -24
  46. cartography/intel/aws/ecr.py +88 -32
  47. cartography/intel/aws/ecs.py +83 -47
  48. cartography/intel/aws/eks.py +55 -29
  49. cartography/intel/aws/elasticache.py +42 -18
  50. cartography/intel/aws/elasticsearch.py +57 -20
  51. cartography/intel/aws/emr.py +61 -23
  52. cartography/intel/aws/iam.py +401 -145
  53. cartography/intel/aws/iam_instance_profiles.py +22 -22
  54. cartography/intel/aws/identitycenter.py +71 -37
  55. cartography/intel/aws/inspector.py +159 -89
  56. cartography/intel/aws/kms.py +92 -38
  57. cartography/intel/aws/lambda_function.py +103 -34
  58. cartography/intel/aws/organizations.py +30 -10
  59. cartography/intel/aws/permission_relationships.py +133 -51
  60. cartography/intel/aws/rds.py +249 -85
  61. cartography/intel/aws/redshift.py +107 -46
  62. cartography/intel/aws/resourcegroupstaggingapi.py +120 -66
  63. cartography/intel/aws/resources.py +53 -44
  64. cartography/intel/aws/route53.py +108 -61
  65. cartography/intel/aws/s3.py +168 -83
  66. cartography/intel/aws/s3accountpublicaccessblock.py +157 -0
  67. cartography/intel/aws/secretsmanager.py +24 -12
  68. cartography/intel/aws/securityhub.py +20 -9
  69. cartography/intel/aws/sns.py +166 -0
  70. cartography/intel/aws/sqs.py +60 -28
  71. cartography/intel/aws/ssm.py +70 -30
  72. cartography/intel/aws/util/arns.py +7 -7
  73. cartography/intel/aws/util/common.py +31 -4
  74. cartography/intel/azure/__init__.py +78 -19
  75. cartography/intel/azure/compute.py +101 -27
  76. cartography/intel/azure/cosmosdb.py +496 -170
  77. cartography/intel/azure/sql.py +296 -105
  78. cartography/intel/azure/storage.py +322 -113
  79. cartography/intel/azure/subscription.py +39 -23
  80. cartography/intel/azure/tenant.py +13 -4
  81. cartography/intel/azure/util/credentials.py +95 -55
  82. cartography/intel/bigfix/__init__.py +2 -2
  83. cartography/intel/bigfix/computers.py +93 -65
  84. cartography/intel/create_indexes.py +3 -2
  85. cartography/intel/crowdstrike/__init__.py +11 -9
  86. cartography/intel/crowdstrike/endpoints.py +5 -1
  87. cartography/intel/crowdstrike/spotlight.py +8 -3
  88. cartography/intel/cve/__init__.py +46 -13
  89. cartography/intel/cve/feed.py +48 -12
  90. cartography/intel/digitalocean/__init__.py +22 -13
  91. cartography/intel/digitalocean/compute.py +75 -108
  92. cartography/intel/digitalocean/management.py +44 -80
  93. cartography/intel/digitalocean/platform.py +48 -43
  94. cartography/intel/dns.py +36 -10
  95. cartography/intel/duo/__init__.py +21 -16
  96. cartography/intel/duo/api_host.py +14 -9
  97. cartography/intel/duo/endpoints.py +50 -45
  98. cartography/intel/duo/groups.py +18 -14
  99. cartography/intel/duo/phones.py +37 -34
  100. cartography/intel/duo/tokens.py +26 -23
  101. cartography/intel/duo/users.py +54 -50
  102. cartography/intel/duo/web_authn_credentials.py +30 -25
  103. cartography/intel/entra/__init__.py +25 -7
  104. cartography/intel/entra/ou.py +112 -0
  105. cartography/intel/entra/users.py +69 -63
  106. cartography/intel/gcp/__init__.py +185 -49
  107. cartography/intel/gcp/compute.py +418 -231
  108. cartography/intel/gcp/crm.py +96 -43
  109. cartography/intel/gcp/dns.py +60 -19
  110. cartography/intel/gcp/gke.py +72 -38
  111. cartography/intel/gcp/iam.py +61 -41
  112. cartography/intel/gcp/storage.py +84 -55
  113. cartography/intel/github/__init__.py +13 -11
  114. cartography/intel/github/repos.py +270 -137
  115. cartography/intel/github/teams.py +170 -88
  116. cartography/intel/github/users.py +70 -39
  117. cartography/intel/github/util.py +36 -34
  118. cartography/intel/gsuite/__init__.py +47 -26
  119. cartography/intel/gsuite/api.py +73 -30
  120. cartography/intel/jamf/__init__.py +19 -1
  121. cartography/intel/jamf/computers.py +30 -7
  122. cartography/intel/jamf/util.py +7 -2
  123. cartography/intel/kandji/__init__.py +6 -3
  124. cartography/intel/kandji/devices.py +14 -8
  125. cartography/intel/kubernetes/namespaces.py +7 -4
  126. cartography/intel/kubernetes/pods.py +7 -4
  127. cartography/intel/kubernetes/services.py +8 -4
  128. cartography/intel/lastpass/__init__.py +2 -2
  129. cartography/intel/lastpass/users.py +23 -12
  130. cartography/intel/oci/__init__.py +44 -11
  131. cartography/intel/oci/iam.py +134 -38
  132. cartography/intel/oci/organizations.py +13 -6
  133. cartography/intel/oci/utils.py +43 -20
  134. cartography/intel/okta/__init__.py +66 -15
  135. cartography/intel/okta/applications.py +42 -20
  136. cartography/intel/okta/awssaml.py +93 -33
  137. cartography/intel/okta/factors.py +16 -4
  138. cartography/intel/okta/groups.py +56 -29
  139. cartography/intel/okta/organization.py +5 -1
  140. cartography/intel/okta/origins.py +6 -2
  141. cartography/intel/okta/roles.py +15 -5
  142. cartography/intel/okta/users.py +20 -8
  143. cartography/intel/okta/utils.py +6 -4
  144. cartography/intel/pagerduty/__init__.py +8 -7
  145. cartography/intel/pagerduty/escalation_policies.py +18 -6
  146. cartography/intel/pagerduty/schedules.py +12 -4
  147. cartography/intel/pagerduty/services.py +11 -4
  148. cartography/intel/pagerduty/teams.py +8 -3
  149. cartography/intel/pagerduty/users.py +3 -1
  150. cartography/intel/pagerduty/vendors.py +3 -1
  151. cartography/intel/semgrep/__init__.py +24 -6
  152. cartography/intel/semgrep/dependencies.py +50 -28
  153. cartography/intel/semgrep/deployment.py +3 -1
  154. cartography/intel/semgrep/findings.py +42 -18
  155. cartography/intel/snipeit/__init__.py +17 -3
  156. cartography/intel/snipeit/asset.py +12 -6
  157. cartography/intel/snipeit/user.py +8 -5
  158. cartography/intel/snipeit/util.py +9 -4
  159. cartography/models/aws/apigateway.py +21 -17
  160. cartography/models/aws/apigatewaycertificate.py +28 -22
  161. cartography/models/aws/apigatewayresource.py +28 -20
  162. cartography/models/aws/apigatewaystage.py +33 -25
  163. cartography/models/aws/cloudtrail/__init__.py +0 -0
  164. cartography/models/aws/cloudtrail/trail.py +61 -0
  165. cartography/models/aws/dynamodb/gsi.py +30 -22
  166. cartography/models/aws/dynamodb/tables.py +25 -17
  167. cartography/models/aws/ec2/auto_scaling_groups.py +102 -82
  168. cartography/models/aws/ec2/images.py +36 -34
  169. cartography/models/aws/ec2/instances.py +51 -45
  170. cartography/models/aws/ec2/keypair.py +21 -16
  171. cartography/models/aws/ec2/keypair_instance.py +28 -21
  172. cartography/models/aws/ec2/launch_configurations.py +30 -26
  173. cartography/models/aws/ec2/launch_template_versions.py +48 -38
  174. cartography/models/aws/ec2/launch_templates.py +21 -17
  175. cartography/models/aws/ec2/load_balancer_listeners.py +27 -23
  176. cartography/models/aws/ec2/load_balancers.py +47 -37
  177. cartography/models/aws/ec2/network_acl_rules.py +38 -30
  178. cartography/models/aws/ec2/network_acls.py +38 -29
  179. cartography/models/aws/ec2/networkinterface_instance.py +52 -39
  180. cartography/models/aws/ec2/networkinterfaces.py +53 -37
  181. cartography/models/aws/ec2/privateip_networkinterface.py +32 -22
  182. cartography/models/aws/ec2/reservations.py +18 -14
  183. cartography/models/aws/ec2/route_table_associations.py +97 -0
  184. cartography/models/aws/ec2/route_tables.py +128 -0
  185. cartography/models/aws/ec2/routes.py +85 -0
  186. cartography/models/aws/ec2/securitygroup_instance.py +29 -20
  187. cartography/models/aws/ec2/securitygroup_networkinterface.py +24 -15
  188. cartography/models/aws/ec2/subnet_instance.py +24 -19
  189. cartography/models/aws/ec2/subnet_networkinterface.py +40 -31
  190. cartography/models/aws/ec2/volumes.py +47 -40
  191. cartography/models/aws/eks/clusters.py +23 -21
  192. cartography/models/aws/emr.py +32 -30
  193. cartography/models/aws/iam/instanceprofile.py +33 -24
  194. cartography/models/aws/identitycenter/awsidentitycenter.py +18 -14
  195. cartography/models/aws/identitycenter/awspermissionset.py +37 -29
  196. cartography/models/aws/identitycenter/awsssouser.py +23 -21
  197. cartography/models/aws/inspector/findings.py +77 -65
  198. cartography/models/aws/inspector/packages.py +35 -29
  199. cartography/models/aws/s3/__init__.py +0 -0
  200. cartography/models/aws/s3/account_public_access_block.py +51 -0
  201. cartography/models/aws/sns/__init__.py +0 -0
  202. cartography/models/aws/sns/topic.py +50 -0
  203. cartography/models/aws/ssm/instance_information.py +51 -39
  204. cartography/models/aws/ssm/instance_patch.py +32 -26
  205. cartography/models/bigfix/bigfix_computer.py +42 -38
  206. cartography/models/bigfix/bigfix_root.py +3 -3
  207. cartography/models/core/common.py +12 -10
  208. cartography/models/core/nodes.py +5 -2
  209. cartography/models/core/relationships.py +14 -6
  210. cartography/models/crowdstrike/hosts.py +37 -35
  211. cartography/models/cve/cve.py +34 -32
  212. cartography/models/cve/cve_feed.py +6 -6
  213. cartography/models/digitalocean/__init__.py +0 -0
  214. cartography/models/digitalocean/account.py +21 -0
  215. cartography/models/digitalocean/droplet.py +56 -0
  216. cartography/models/digitalocean/project.py +48 -0
  217. cartography/models/duo/api_host.py +3 -3
  218. cartography/models/duo/endpoint.py +43 -41
  219. cartography/models/duo/group.py +14 -14
  220. cartography/models/duo/phone.py +27 -27
  221. cartography/models/duo/token.py +16 -16
  222. cartography/models/duo/user.py +46 -44
  223. cartography/models/duo/web_authn_credential.py +27 -19
  224. cartography/models/entra/ou.py +48 -0
  225. cartography/models/entra/tenant.py +24 -18
  226. cartography/models/entra/user.py +64 -48
  227. cartography/models/gcp/iam.py +23 -23
  228. cartography/models/github/orgs.py +5 -4
  229. cartography/models/github/teams.py +37 -31
  230. cartography/models/github/users.py +34 -23
  231. cartography/models/kandji/device.py +22 -16
  232. cartography/models/kandji/tenant.py +6 -4
  233. cartography/models/lastpass/tenant.py +3 -3
  234. cartography/models/lastpass/user.py +32 -28
  235. cartography/models/semgrep/dependencies.py +36 -24
  236. cartography/models/semgrep/deployment.py +5 -5
  237. cartography/models/semgrep/findings.py +58 -42
  238. cartography/models/semgrep/locations.py +27 -21
  239. cartography/models/snipeit/asset.py +30 -21
  240. cartography/models/snipeit/tenant.py +6 -4
  241. cartography/models/snipeit/user.py +19 -12
  242. cartography/stats.py +3 -3
  243. cartography/sync.py +107 -31
  244. cartography/util.py +84 -62
  245. {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/METADATA +3 -14
  246. cartography-0.103.0rc1.dist-info/RECORD +396 -0
  247. {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/WHEEL +1 -1
  248. cartography-0.102.0rc1.dist-info/RECORD +0 -377
  249. {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/entry_points.txt +0 -0
  250. {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/licenses/LICENSE +0 -0
  251. {cartography-0.102.0rc1.dist-info → cartography-0.103.0rc1.dist-info}/top_level.txt +0 -0
@@ -14,30 +14,52 @@ logger = logging.getLogger(__name__)
14
14
 
15
15
  @timeit
16
16
  @aws_handle_regions
17
- def get_redshift_cluster_data(boto3_session: boto3.session.Session, region: str) -> List[Dict]:
18
- client = boto3_session.client('redshift', region_name=region)
19
- paginator = client.get_paginator('describe_clusters')
17
+ def get_redshift_cluster_data(
18
+ boto3_session: boto3.session.Session,
19
+ region: str,
20
+ ) -> List[Dict]:
21
+ client = boto3_session.client("redshift", region_name=region)
22
+ paginator = client.get_paginator("describe_clusters")
20
23
  clusters: List[Dict] = []
21
24
  for page in paginator.paginate():
22
- clusters.extend(page['Clusters'])
25
+ clusters.extend(page["Clusters"])
23
26
  return clusters
24
27
 
25
28
 
26
- def _make_redshift_cluster_arn(region: str, aws_account_id: str, cluster_identifier: str) -> str:
29
+ def _make_redshift_cluster_arn(
30
+ region: str,
31
+ aws_account_id: str,
32
+ cluster_identifier: str,
33
+ ) -> str:
27
34
  """Cluster ARN format: https://docs.aws.amazon.com/redshift/latest/mgmt/redshift-iam-access-control-overview.html"""
28
- return f'arn:aws:redshift:{region}:{aws_account_id}:cluster:{cluster_identifier}'
35
+ return f"arn:aws:redshift:{region}:{aws_account_id}:cluster:{cluster_identifier}"
29
36
 
30
37
 
31
- def transform_redshift_cluster_data(clusters: List[Dict], region: str, current_aws_account_id: str) -> None:
38
+ def transform_redshift_cluster_data(
39
+ clusters: List[Dict],
40
+ region: str,
41
+ current_aws_account_id: str,
42
+ ) -> None:
32
43
  for cluster in clusters:
33
- cluster['arn'] = _make_redshift_cluster_arn(region, current_aws_account_id, cluster["ClusterIdentifier"])
34
- cluster['ClusterCreateTime'] = str(cluster['ClusterCreateTime']) if 'ClusterCreateTime' in cluster else None
44
+ cluster["arn"] = _make_redshift_cluster_arn(
45
+ region,
46
+ current_aws_account_id,
47
+ cluster["ClusterIdentifier"],
48
+ )
49
+ cluster["ClusterCreateTime"] = (
50
+ str(cluster["ClusterCreateTime"])
51
+ if "ClusterCreateTime" in cluster
52
+ else None
53
+ )
35
54
 
36
55
 
37
56
  @timeit
38
57
  def load_redshift_cluster_data(
39
- neo4j_session: neo4j.Session, clusters: List[Dict], region: str,
40
- current_aws_account_id: str, aws_update_tag: int,
58
+ neo4j_session: neo4j.Session,
59
+ clusters: List[Dict],
60
+ region: str,
61
+ current_aws_account_id: str,
62
+ aws_update_tag: int,
41
63
  ) -> None:
42
64
  ingest_cluster = """
43
65
  MERGE (cluster:RedshiftCluster{id: $Arn})
@@ -68,21 +90,21 @@ def load_redshift_cluster_data(
68
90
  for cluster in clusters:
69
91
  neo4j_session.run(
70
92
  ingest_cluster,
71
- Arn=cluster['arn'],
72
- AZ=cluster['AvailabilityZone'],
73
- ClusterCreateTime=cluster['ClusterCreateTime'],
74
- ClusterIdentifier=cluster['ClusterIdentifier'],
75
- ClusterRevisionNumber=cluster['ClusterRevisionNumber'],
76
- ClusterStatus=cluster['ClusterStatus'],
77
- DBName=cluster['DBName'],
78
- Encrypted=cluster['Encrypted'],
79
- EndpointAddress=cluster.get('Endpoint').get('Address'), # type: ignore
80
- EndpointPort=cluster.get('Endpoint').get('Port'), # type: ignore
81
- MasterUsername=cluster['MasterUsername'],
82
- NodeType=cluster['NodeType'],
83
- NumberOfNodes=cluster['NumberOfNodes'],
84
- PubliclyAccessible=cluster['PubliclyAccessible'],
85
- VpcId=cluster.get('VpcId'),
93
+ Arn=cluster["arn"],
94
+ AZ=cluster["AvailabilityZone"],
95
+ ClusterCreateTime=cluster["ClusterCreateTime"],
96
+ ClusterIdentifier=cluster["ClusterIdentifier"],
97
+ ClusterRevisionNumber=cluster["ClusterRevisionNumber"],
98
+ ClusterStatus=cluster["ClusterStatus"],
99
+ DBName=cluster["DBName"],
100
+ Encrypted=cluster["Encrypted"],
101
+ EndpointAddress=cluster.get("Endpoint").get("Address"), # type: ignore
102
+ EndpointPort=cluster.get("Endpoint").get("Port"), # type: ignore
103
+ MasterUsername=cluster["MasterUsername"],
104
+ NodeType=cluster["NodeType"],
105
+ NumberOfNodes=cluster["NumberOfNodes"],
106
+ PubliclyAccessible=cluster["PubliclyAccessible"],
107
+ VpcId=cluster.get("VpcId"),
86
108
  Region=region,
87
109
  AWS_ACCOUNT_ID=current_aws_account_id,
88
110
  aws_update_tag=aws_update_tag,
@@ -93,7 +115,11 @@ def load_redshift_cluster_data(
93
115
 
94
116
 
95
117
  @timeit
96
- def _attach_ec2_security_groups(neo4j_session: neo4j.Session, cluster: Dict, aws_update_tag: int) -> None:
118
+ def _attach_ec2_security_groups(
119
+ neo4j_session: neo4j.Session,
120
+ cluster: Dict,
121
+ aws_update_tag: int,
122
+ ) -> None:
97
123
  attach_cluster_to_group = """
98
124
  MATCH (c:RedshiftCluster{id:$ClusterArn})
99
125
  MERGE (sg:EC2SecurityGroup{id:$GroupId})
@@ -101,17 +127,21 @@ def _attach_ec2_security_groups(neo4j_session: neo4j.Session, cluster: Dict, aws
101
127
  ON CREATE SET m.firstseen = timestamp()
102
128
  SET m.lastupdated = $aws_update_tag
103
129
  """
104
- for group in cluster.get('VpcSecurityGroups', []):
130
+ for group in cluster.get("VpcSecurityGroups", []):
105
131
  neo4j_session.run(
106
132
  attach_cluster_to_group,
107
- ClusterArn=cluster['arn'],
108
- GroupId=group['VpcSecurityGroupId'],
133
+ ClusterArn=cluster["arn"],
134
+ GroupId=group["VpcSecurityGroupId"],
109
135
  aws_update_tag=aws_update_tag,
110
136
  )
111
137
 
112
138
 
113
139
  @timeit
114
- def _attach_iam_roles(neo4j_session: neo4j.Session, cluster: Dict, aws_update_tag: int) -> None:
140
+ def _attach_iam_roles(
141
+ neo4j_session: neo4j.Session,
142
+ cluster: Dict,
143
+ aws_update_tag: int,
144
+ ) -> None:
115
145
  attach_cluster_to_role = """
116
146
  MATCH (c:RedshiftCluster{id:$ClusterArn})
117
147
  MERGE (p:AWSPrincipal{arn:$RoleArn})
@@ -119,17 +149,21 @@ def _attach_iam_roles(neo4j_session: neo4j.Session, cluster: Dict, aws_update_ta
119
149
  ON CREATE SET s.firstseen = timestamp()
120
150
  SET s.lastupdated = $aws_update_tag
121
151
  """
122
- for role in cluster.get('IamRoles', []):
152
+ for role in cluster.get("IamRoles", []):
123
153
  neo4j_session.run(
124
154
  attach_cluster_to_role,
125
- ClusterArn=cluster['arn'],
126
- RoleArn=role['IamRoleArn'],
155
+ ClusterArn=cluster["arn"],
156
+ RoleArn=role["IamRoleArn"],
127
157
  aws_update_tag=aws_update_tag,
128
158
  )
129
159
 
130
160
 
131
161
  @timeit
132
- def _attach_aws_vpc(neo4j_session: neo4j.Session, cluster: Dict, aws_update_tag: int) -> None:
162
+ def _attach_aws_vpc(
163
+ neo4j_session: neo4j.Session,
164
+ cluster: Dict,
165
+ aws_update_tag: int,
166
+ ) -> None:
133
167
  attach_cluster_to_vpc = """
134
168
  MATCH (c:RedshiftCluster{id:$ClusterArn})
135
169
  MERGE (v:AWSVpc{id:$VpcId})
@@ -137,36 +171,63 @@ def _attach_aws_vpc(neo4j_session: neo4j.Session, cluster: Dict, aws_update_tag:
137
171
  ON CREATE SET m.firstseen = timestamp()
138
172
  SET m.lastupdated = $aws_update_tag
139
173
  """
140
- if cluster.get('VpcId'):
174
+ if cluster.get("VpcId"):
141
175
  neo4j_session.run(
142
176
  attach_cluster_to_vpc,
143
- ClusterArn=cluster['arn'],
144
- VpcId=cluster['VpcId'],
177
+ ClusterArn=cluster["arn"],
178
+ VpcId=cluster["VpcId"],
145
179
  aws_update_tag=aws_update_tag,
146
180
  )
147
181
 
148
182
 
149
183
  @timeit
150
184
  def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
151
- run_cleanup_job('aws_import_redshift_clusters_cleanup.json', neo4j_session, common_job_parameters)
185
+ run_cleanup_job(
186
+ "aws_import_redshift_clusters_cleanup.json",
187
+ neo4j_session,
188
+ common_job_parameters,
189
+ )
152
190
 
153
191
 
154
192
  @timeit
155
193
  def sync_redshift_clusters(
156
- neo4j_session: neo4j.Session, boto3_session: boto3.session.Session, region: str,
157
- current_aws_account_id: str, aws_update_tag: int,
194
+ neo4j_session: neo4j.Session,
195
+ boto3_session: boto3.session.Session,
196
+ region: str,
197
+ current_aws_account_id: str,
198
+ aws_update_tag: int,
158
199
  ) -> None:
159
200
  data = get_redshift_cluster_data(boto3_session, region)
160
201
  transform_redshift_cluster_data(data, region, current_aws_account_id)
161
- load_redshift_cluster_data(neo4j_session, data, region, current_aws_account_id, aws_update_tag)
202
+ load_redshift_cluster_data(
203
+ neo4j_session,
204
+ data,
205
+ region,
206
+ current_aws_account_id,
207
+ aws_update_tag,
208
+ )
162
209
 
163
210
 
164
211
  @timeit
165
212
  def sync(
166
- neo4j_session: neo4j.Session, boto3_session: boto3.session.Session, regions: List[str], current_aws_account_id: str,
167
- update_tag: int, common_job_parameters: Dict,
213
+ neo4j_session: neo4j.Session,
214
+ boto3_session: boto3.session.Session,
215
+ regions: List[str],
216
+ current_aws_account_id: str,
217
+ update_tag: int,
218
+ common_job_parameters: Dict,
168
219
  ) -> None:
169
220
  for region in regions:
170
- logger.info("Syncing Redshift clusters for region '%s' in account '%s'.", region, current_aws_account_id)
171
- sync_redshift_clusters(neo4j_session, boto3_session, region, current_aws_account_id, update_tag)
221
+ logger.info(
222
+ "Syncing Redshift clusters for region '%s' in account '%s'.",
223
+ region,
224
+ current_aws_account_id,
225
+ )
226
+ sync_redshift_clusters(
227
+ neo4j_session,
228
+ boto3_session,
229
+ region,
230
+ current_aws_account_id,
231
+ update_tag,
232
+ )
172
233
  cleanup(neo4j_session, common_job_parameters)
@@ -22,7 +22,7 @@ def get_short_id_from_ec2_arn(arn: str) -> str:
22
22
  :param arn: The ARN
23
23
  :return: The resource ID
24
24
  """
25
- return arn.split('/')[-1]
25
+ return arn.split("/")[-1]
26
26
 
27
27
 
28
28
  def get_bucket_name_from_arn(bucket_arn: str) -> str:
@@ -32,7 +32,7 @@ def get_bucket_name_from_arn(bucket_arn: str) -> str:
32
32
  :param arn: The S3 bucket's full ARN
33
33
  :return: The S3 bucket's name
34
34
  """
35
- return bucket_arn.split(':')[-1]
35
+ return bucket_arn.split(":")[-1]
36
36
 
37
37
 
38
38
  def get_short_id_from_elb_arn(alb_arn: str) -> str:
@@ -42,7 +42,7 @@ def get_short_id_from_elb_arn(alb_arn: str) -> str:
42
42
  :param arn: The ELB's full ARN
43
43
  :return: The ELB's name
44
44
  """
45
- return alb_arn.split('/')[-1]
45
+ return alb_arn.split("/")[-1]
46
46
 
47
47
 
48
48
  def get_short_id_from_lb2_arn(alb_arn: str) -> str:
@@ -53,7 +53,7 @@ def get_short_id_from_lb2_arn(alb_arn: str) -> str:
53
53
  :param arn: The (N|A)LB's full ARN
54
54
  :return: The (N|A)LB's name
55
55
  """
56
- return alb_arn.split('/')[-2]
56
+ return alb_arn.split("/")[-2]
57
57
 
58
58
 
59
59
  # We maintain a mapping from AWS resource types to their associated labels and unique identifiers.
@@ -64,79 +64,121 @@ def get_short_id_from_lb2_arn(alb_arn: str) -> str:
64
64
  # cartography uses.
65
65
  # TODO - we should make EC2 and S3 assets query-able by their full ARN so that we don't need this workaround.
66
66
  TAG_RESOURCE_TYPE_MAPPINGS: Dict = {
67
- 'autoscaling:autoScalingGroup': {'label': 'AutoScalingGroup', 'property': 'arn'},
68
- 'dynamodb:table': {'label': 'DynamoDBTable', 'property': 'id'},
69
- 'ec2:instance': {'label': 'EC2Instance', 'property': 'id', 'id_func': get_short_id_from_ec2_arn},
70
- 'ec2:internet-gateway': {'label': 'AWSInternetGateway', 'property': 'id', 'id_func': get_short_id_from_ec2_arn},
71
- 'ec2:key-pair': {'label': 'EC2KeyPair', 'property': 'id'},
72
- 'ec2:network-interface': {'label': 'NetworkInterface', 'property': 'id', 'id_func': get_short_id_from_ec2_arn},
73
- 'ecr:repository': {'label': 'ECRRepository', 'property': 'id'},
74
- 'ec2:security-group': {'label': 'EC2SecurityGroup', 'property': 'id', 'id_func': get_short_id_from_ec2_arn},
75
- 'ec2:subnet': {'label': 'EC2Subnet', 'property': 'subnetid', 'id_func': get_short_id_from_ec2_arn},
76
- 'ec2:transit-gateway': {'label': 'AWSTransitGateway', 'property': 'id'},
77
- 'ec2:transit-gateway-attachment': {'label': 'AWSTransitGatewayAttachment', 'property': 'id'},
78
- 'ec2:vpc': {'label': 'AWSVpc', 'property': 'id', 'id_func': get_short_id_from_ec2_arn},
79
- 'ec2:volume': {'label': 'EBSVolume', 'property': 'id', 'id_func': get_short_id_from_ec2_arn},
80
- 'ec2:elastic-ip-address': {'label': 'ElasticIPAddress', 'property': 'id', 'id_func': get_short_id_from_ec2_arn},
81
- 'ecs:cluster': {'label': 'ECSCluster', 'property': 'id'},
82
- 'ecs:container': {'label': 'ECSContainer', 'property': 'id'},
83
- 'ecs:container-instance': {'label': 'ECSContainerInstance', 'property': 'id'},
84
- 'ecs:task': {'label': 'ECSTask', 'property': 'id'},
85
- 'ecs:task-definition': {'label': 'ECSTaskDefinition', 'property': 'id'},
86
- 'eks:cluster': {'label': 'EKSCluster', 'property': 'id'},
87
- 'elasticache:cluster': {'label': 'ElasticacheCluster', 'property': 'arn'},
88
- 'elasticloadbalancing:loadbalancer': {
89
- 'label': 'LoadBalancer', 'property':
90
- 'name', 'id_func': get_short_id_from_elb_arn,
67
+ "autoscaling:autoScalingGroup": {"label": "AutoScalingGroup", "property": "arn"},
68
+ "dynamodb:table": {"label": "DynamoDBTable", "property": "id"},
69
+ "ec2:instance": {
70
+ "label": "EC2Instance",
71
+ "property": "id",
72
+ "id_func": get_short_id_from_ec2_arn,
91
73
  },
92
- 'elasticloadbalancing:loadbalancer/app': {
93
- 'label': 'LoadBalancerV2',
94
- 'property': 'name', 'id_func': get_short_id_from_lb2_arn,
74
+ "ec2:internet-gateway": {
75
+ "label": "AWSInternetGateway",
76
+ "property": "id",
77
+ "id_func": get_short_id_from_ec2_arn,
95
78
  },
96
- 'elasticloadbalancing:loadbalancer/net': {
97
- 'label': 'LoadBalancerV2',
98
- 'property': 'name', 'id_func': get_short_id_from_lb2_arn,
79
+ "ec2:key-pair": {"label": "EC2KeyPair", "property": "id"},
80
+ "ec2:network-interface": {
81
+ "label": "NetworkInterface",
82
+ "property": "id",
83
+ "id_func": get_short_id_from_ec2_arn,
99
84
  },
100
- 'elasticmapreduce:cluster': {'label': 'EMRCluster', 'property': 'arn'},
101
- 'es:domain': {'label': 'ESDomain', 'property': 'arn'},
102
- 'kms:key': {'label': 'KMSKey', 'property': 'arn'},
103
- 'iam:group': {'label': 'AWSGroup', 'property': 'arn'},
104
- 'iam:role': {'label': 'AWSRole', 'property': 'arn'},
105
- 'iam:user': {'label': 'AWSUser', 'property': 'arn'},
106
- 'lambda:function': {'label': 'AWSLambda', 'property': 'id'},
107
- 'redshift:cluster': {'label': 'RedshiftCluster', 'property': 'id'},
108
- 'rds:db': {'label': 'RDSInstance', 'property': 'id'},
109
- 'rds:subgrp': {'label': 'DBSubnetGroup', 'property': 'id'},
110
- 'rds:cluster': {'label': 'RDSCluster', 'property': 'id'},
111
- 'rds:snapshot': {'label': 'RDSSnapshot', 'property': 'id'},
85
+ "ecr:repository": {"label": "ECRRepository", "property": "id"},
86
+ "ec2:security-group": {
87
+ "label": "EC2SecurityGroup",
88
+ "property": "id",
89
+ "id_func": get_short_id_from_ec2_arn,
90
+ },
91
+ "ec2:subnet": {
92
+ "label": "EC2Subnet",
93
+ "property": "subnetid",
94
+ "id_func": get_short_id_from_ec2_arn,
95
+ },
96
+ "ec2:transit-gateway": {"label": "AWSTransitGateway", "property": "id"},
97
+ "ec2:transit-gateway-attachment": {
98
+ "label": "AWSTransitGatewayAttachment",
99
+ "property": "id",
100
+ },
101
+ "ec2:vpc": {
102
+ "label": "AWSVpc",
103
+ "property": "id",
104
+ "id_func": get_short_id_from_ec2_arn,
105
+ },
106
+ "ec2:volume": {
107
+ "label": "EBSVolume",
108
+ "property": "id",
109
+ "id_func": get_short_id_from_ec2_arn,
110
+ },
111
+ "ec2:elastic-ip-address": {
112
+ "label": "ElasticIPAddress",
113
+ "property": "id",
114
+ "id_func": get_short_id_from_ec2_arn,
115
+ },
116
+ "ecs:cluster": {"label": "ECSCluster", "property": "id"},
117
+ "ecs:container": {"label": "ECSContainer", "property": "id"},
118
+ "ecs:container-instance": {"label": "ECSContainerInstance", "property": "id"},
119
+ "ecs:task": {"label": "ECSTask", "property": "id"},
120
+ "ecs:task-definition": {"label": "ECSTaskDefinition", "property": "id"},
121
+ "eks:cluster": {"label": "EKSCluster", "property": "id"},
122
+ "elasticache:cluster": {"label": "ElasticacheCluster", "property": "arn"},
123
+ "elasticloadbalancing:loadbalancer": {
124
+ "label": "LoadBalancer",
125
+ "property": "name",
126
+ "id_func": get_short_id_from_elb_arn,
127
+ },
128
+ "elasticloadbalancing:loadbalancer/app": {
129
+ "label": "LoadBalancerV2",
130
+ "property": "name",
131
+ "id_func": get_short_id_from_lb2_arn,
132
+ },
133
+ "elasticloadbalancing:loadbalancer/net": {
134
+ "label": "LoadBalancerV2",
135
+ "property": "name",
136
+ "id_func": get_short_id_from_lb2_arn,
137
+ },
138
+ "elasticmapreduce:cluster": {"label": "EMRCluster", "property": "arn"},
139
+ "es:domain": {"label": "ESDomain", "property": "arn"},
140
+ "kms:key": {"label": "KMSKey", "property": "arn"},
141
+ "iam:group": {"label": "AWSGroup", "property": "arn"},
142
+ "iam:role": {"label": "AWSRole", "property": "arn"},
143
+ "iam:user": {"label": "AWSUser", "property": "arn"},
144
+ "lambda:function": {"label": "AWSLambda", "property": "id"},
145
+ "redshift:cluster": {"label": "RedshiftCluster", "property": "id"},
146
+ "rds:db": {"label": "RDSInstance", "property": "id"},
147
+ "rds:subgrp": {"label": "DBSubnetGroup", "property": "id"},
148
+ "rds:cluster": {"label": "RDSCluster", "property": "id"},
149
+ "rds:snapshot": {"label": "RDSSnapshot", "property": "id"},
112
150
  # Buckets are the only objects in the S3 service: https://docs.aws.amazon.com/AmazonS3/latest/dev/s3-arn-format.html
113
- 's3': {'label': 'S3Bucket', 'property': 'id', 'id_func': get_bucket_name_from_arn},
114
- 'secretsmanager:secret': {'label': 'SecretsManagerSecret', 'property': 'id'},
115
- 'sqs': {'label': 'SQSQueue', 'property': 'id'},
151
+ "s3": {"label": "S3Bucket", "property": "id", "id_func": get_bucket_name_from_arn},
152
+ "secretsmanager:secret": {"label": "SecretsManagerSecret", "property": "id"},
153
+ "sqs": {"label": "SQSQueue", "property": "id"},
116
154
  }
117
155
 
118
156
 
119
157
  @timeit
120
158
  @aws_handle_regions
121
- def get_tags(boto3_session: boto3.session.Session, resource_type: str, region: str) -> List[Dict]:
159
+ def get_tags(
160
+ boto3_session: boto3.session.Session,
161
+ resource_type: str,
162
+ region: str,
163
+ ) -> List[Dict]:
122
164
  """
123
165
  Create boto3 client and retrieve tag data.
124
166
  """
125
167
  # this is a temporary workaround to populate AWS tags for IAM roles.
126
168
  # resourcegroupstaggingapi does not support IAM roles and no ETA is provided
127
169
  # TODO: when resourcegroupstaggingapi supports iam:role, remove this condition block
128
- if resource_type == 'iam:role':
170
+ if resource_type == "iam:role":
129
171
  return get_role_tags(boto3_session)
130
172
 
131
- client = boto3_session.client('resourcegroupstaggingapi', region_name=region)
132
- paginator = client.get_paginator('get_resources')
173
+ client = boto3_session.client("resourcegroupstaggingapi", region_name=region)
174
+ paginator = client.get_paginator("get_resources")
133
175
  resources: List[Dict] = []
134
176
  for page in paginator.paginate(
135
177
  # Only ingest tags for resources that Cartography supports.
136
178
  # This is just a starting list; there may be others supported by this API.
137
179
  ResourceTypeFilters=[resource_type],
138
180
  ):
139
- resources.extend(page['ResourceTagMappingList'])
181
+ resources.extend(page["ResourceTagMappingList"])
140
182
  return resources
141
183
 
142
184
 
@@ -148,7 +190,8 @@ def _load_tags_tx(
148
190
  current_aws_account_id: str,
149
191
  aws_update_tag: int,
150
192
  ) -> None:
151
- INGEST_TAG_TEMPLATE = Template("""
193
+ INGEST_TAG_TEMPLATE = Template(
194
+ """
152
195
  UNWIND $TagData as tag_mapping
153
196
  UNWIND tag_mapping.Tags as input_tag
154
197
  MATCH
@@ -165,10 +208,11 @@ def _load_tags_tx(
165
208
  MERGE (resource)-[r:TAGGED]->(aws_tag)
166
209
  SET r.lastupdated = $UpdateTag,
167
210
  r.firstseen = timestamp()
168
- """)
211
+ """,
212
+ )
169
213
  query = INGEST_TAG_TEMPLATE.safe_substitute(
170
- resource_label=TAG_RESOURCE_TYPE_MAPPINGS[resource_type]['label'],
171
- property=TAG_RESOURCE_TYPE_MAPPINGS[resource_type]['property'],
214
+ resource_label=TAG_RESOURCE_TYPE_MAPPINGS[resource_type]["label"],
215
+ property=TAG_RESOURCE_TYPE_MAPPINGS[resource_type]["property"],
172
216
  )
173
217
  tx.run(
174
218
  query,
@@ -205,20 +249,26 @@ def load_tags(
205
249
  @timeit
206
250
  def transform_tags(tag_data: Dict, resource_type: str) -> None:
207
251
  for tag_mapping in tag_data:
208
- tag_mapping['resource_id'] = compute_resource_id(tag_mapping, resource_type)
252
+ tag_mapping["resource_id"] = compute_resource_id(tag_mapping, resource_type)
209
253
 
210
254
 
211
255
  def compute_resource_id(tag_mapping: Dict, resource_type: str) -> str:
212
- resource_id = tag_mapping['ResourceARN']
213
- if 'id_func' in TAG_RESOURCE_TYPE_MAPPINGS[resource_type]:
214
- parse_resource_id_from_arn = TAG_RESOURCE_TYPE_MAPPINGS[resource_type]['id_func']
215
- resource_id = parse_resource_id_from_arn(tag_mapping['ResourceARN'])
256
+ resource_id = tag_mapping["ResourceARN"]
257
+ if "id_func" in TAG_RESOURCE_TYPE_MAPPINGS[resource_type]:
258
+ parse_resource_id_from_arn = TAG_RESOURCE_TYPE_MAPPINGS[resource_type][
259
+ "id_func"
260
+ ]
261
+ resource_id = parse_resource_id_from_arn(tag_mapping["ResourceARN"])
216
262
  return resource_id
217
263
 
218
264
 
219
265
  @timeit
220
266
  def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
221
- run_cleanup_job('aws_import_tags_cleanup.json', neo4j_session, common_job_parameters)
267
+ run_cleanup_job(
268
+ "aws_import_tags_cleanup.json",
269
+ neo4j_session,
270
+ common_job_parameters,
271
+ )
222
272
 
223
273
 
224
274
  @timeit
@@ -232,11 +282,15 @@ def sync(
232
282
  tag_resource_type_mappings: Dict = TAG_RESOURCE_TYPE_MAPPINGS,
233
283
  ) -> None:
234
284
  for region in regions:
235
- logger.info(f"Syncing AWS tags for account {current_aws_account_id} and region {region}")
285
+ logger.info(
286
+ f"Syncing AWS tags for account {current_aws_account_id} and region {region}",
287
+ )
236
288
  for resource_type in tag_resource_type_mappings.keys():
237
289
  tag_data = get_tags(boto3_session, resource_type, region)
238
290
  transform_tags(tag_data, resource_type) # type: ignore
239
- logger.info(f"Loading {len(tag_data)} tags for resource type {resource_type}")
291
+ logger.info(
292
+ f"Loading {len(tag_data)} tags for resource type {resource_type}",
293
+ )
240
294
  load_tags(
241
295
  neo4j_session=neo4j_session,
242
296
  tag_data=tag_data, # type: ignore
@@ -1,7 +1,10 @@
1
1
  from typing import Callable
2
2
  from typing import Dict
3
3
 
4
+ from cartography.intel.aws.ec2.route_tables import sync_route_tables
5
+
4
6
  from . import apigateway
7
+ from . import cloudtrail
5
8
  from . import config
6
9
  from . import dynamodb
7
10
  from . import ecr
@@ -21,8 +24,10 @@ from . import redshift
21
24
  from . import resourcegroupstaggingapi
22
25
  from . import route53
23
26
  from . import s3
27
+ from . import s3accountpublicaccessblock
24
28
  from . import secretsmanager
25
29
  from . import securityhub
30
+ from . import sns
26
31
  from . import sqs
27
32
  from . import ssm
28
33
  from .ec2.auto_scaling_groups import sync_ec2_auto_scaling_groups
@@ -47,50 +52,54 @@ from .ec2.vpc_peerings import sync_vpc_peerings
47
52
  from .iam_instance_profiles import sync_iam_instance_profiles
48
53
 
49
54
  RESOURCE_FUNCTIONS: Dict[str, Callable[..., None]] = {
50
- 'iam': iam.sync,
51
- 'iaminstanceprofiles': sync_iam_instance_profiles,
52
- 's3': s3.sync,
53
- 'dynamodb': dynamodb.sync,
54
- 'ec2:launch_templates': sync_ec2_launch_templates,
55
- 'ec2:autoscalinggroup': sync_ec2_auto_scaling_groups,
55
+ "iam": iam.sync,
56
+ "iaminstanceprofiles": sync_iam_instance_profiles,
57
+ "s3": s3.sync,
58
+ "dynamodb": dynamodb.sync,
59
+ "ec2:launch_templates": sync_ec2_launch_templates,
60
+ "ec2:autoscalinggroup": sync_ec2_auto_scaling_groups,
56
61
  # `ec2:instance` must be included before `ssm` and `ec2:images`,
57
62
  # they rely on EC2Instance data provided by this module.
58
- 'ec2:instance': sync_ec2_instances,
59
- 'ec2:images': sync_ec2_images,
60
- 'ec2:keypair': sync_ec2_key_pairs,
61
- 'ec2:load_balancer': sync_load_balancers,
62
- 'ec2:load_balancer_v2': sync_load_balancer_v2s,
63
- 'ec2:network_acls': sync_network_acls,
64
- 'ec2:network_interface': sync_network_interfaces,
65
- 'ec2:security_group': sync_ec2_security_groupinfo,
66
- 'ec2:subnet': sync_subnets,
67
- 'ec2:tgw': sync_transit_gateways,
68
- 'ec2:vpc': sync_vpc,
69
- 'ec2:vpc_peering': sync_vpc_peerings,
70
- 'ec2:internet_gateway': sync_internet_gateways,
71
- 'ec2:reserved_instances': sync_ec2_reserved_instances,
72
- 'ec2:volumes': sync_ebs_volumes,
73
- 'ec2:snapshots': sync_ebs_snapshots,
74
- 'ecr': ecr.sync,
75
- 'ecs': ecs.sync,
76
- 'eks': eks.sync,
77
- 'elasticache': elasticache.sync,
78
- 'elastic_ip_addresses': sync_elastic_ip_addresses,
79
- 'emr': emr.sync,
80
- 'lambda_function': lambda_function.sync,
81
- 'kms': kms.sync,
82
- 'rds': rds.sync,
83
- 'redshift': redshift.sync,
84
- 'route53': route53.sync,
85
- 'elasticsearch': elasticsearch.sync,
86
- 'permission_relationships': permission_relationships.sync,
87
- 'resourcegroupstaggingapi': resourcegroupstaggingapi.sync,
88
- 'apigateway': apigateway.sync,
89
- 'secretsmanager': secretsmanager.sync,
90
- 'securityhub': securityhub.sync,
91
- 'sqs': sqs.sync,
92
- 'ssm': ssm.sync,
93
- 'inspector': inspector.sync,
94
- 'config': config.sync,
95
- 'identitycenter': identitycenter.sync_identity_center_instances,
63
+ "ec2:instance": sync_ec2_instances,
64
+ "ec2:images": sync_ec2_images,
65
+ "ec2:keypair": sync_ec2_key_pairs,
66
+ "ec2:load_balancer": sync_load_balancers,
67
+ "ec2:load_balancer_v2": sync_load_balancer_v2s,
68
+ "ec2:network_acls": sync_network_acls,
69
+ "ec2:network_interface": sync_network_interfaces,
70
+ "ec2:route_table": sync_route_tables,
71
+ "ec2:security_group": sync_ec2_security_groupinfo,
72
+ "ec2:subnet": sync_subnets,
73
+ "ec2:tgw": sync_transit_gateways,
74
+ "ec2:vpc": sync_vpc,
75
+ "ec2:vpc_peering": sync_vpc_peerings,
76
+ "ec2:internet_gateway": sync_internet_gateways,
77
+ "ec2:reserved_instances": sync_ec2_reserved_instances,
78
+ "ec2:volumes": sync_ebs_volumes,
79
+ "ec2:snapshots": sync_ebs_snapshots,
80
+ "ecr": ecr.sync,
81
+ "ecs": ecs.sync,
82
+ "eks": eks.sync,
83
+ "elasticache": elasticache.sync,
84
+ "elastic_ip_addresses": sync_elastic_ip_addresses,
85
+ "emr": emr.sync,
86
+ "lambda_function": lambda_function.sync,
87
+ "kms": kms.sync,
88
+ "rds": rds.sync,
89
+ "redshift": redshift.sync,
90
+ "route53": route53.sync,
91
+ "elasticsearch": elasticsearch.sync,
92
+ "permission_relationships": permission_relationships.sync,
93
+ "resourcegroupstaggingapi": resourcegroupstaggingapi.sync,
94
+ "apigateway": apigateway.sync,
95
+ "secretsmanager": secretsmanager.sync,
96
+ "securityhub": securityhub.sync,
97
+ "s3accountpublicaccessblock": s3accountpublicaccessblock.sync,
98
+ "sns": sns.sync,
99
+ "sqs": sqs.sync,
100
+ "ssm": ssm.sync,
101
+ "inspector": inspector.sync,
102
+ "config": config.sync,
103
+ "identitycenter": identitycenter.sync_identity_center_instances,
104
+ "cloudtrail": cloudtrail.sync,
96
105
  }