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
@@ -6,23 +6,29 @@ from typing import List
6
6
  import boto3
7
7
  import neo4j
8
8
 
9
- from .util import get_botocore_config
10
9
  from cartography.util import aws_handle_regions
11
10
  from cartography.util import run_cleanup_job
12
11
  from cartography.util import timeit
13
12
 
13
+ from .util import get_botocore_config
14
+
14
15
  logger = logging.getLogger(__name__)
15
16
 
16
17
 
17
18
  @timeit
18
19
  @aws_handle_regions
19
20
  def get_ec2_vpcs(boto3_session: boto3.session.Session, region: str) -> List[Dict]:
20
- client = boto3_session.client('ec2', region_name=region, config=get_botocore_config())
21
- return client.describe_vpcs()['Vpcs']
21
+ client = boto3_session.client(
22
+ "ec2",
23
+ region_name=region,
24
+ config=get_botocore_config(),
25
+ )
26
+ return client.describe_vpcs()["Vpcs"]
22
27
 
23
28
 
24
29
  def _get_cidr_association_statement(block_type: str) -> str:
25
- INGEST_CIDR_TEMPLATE = Template("""
30
+ INGEST_CIDR_TEMPLATE = Template(
31
+ """
26
32
  MATCH (vpc:AWSVpc{id: $VpcId})
27
33
  WITH vpc
28
34
  UNWIND $CidrBlock as block_data
@@ -36,7 +42,8 @@ def _get_cidr_association_statement(block_type: str) -> str:
36
42
  WITH vpc, new_block
37
43
  MERGE (vpc)-[r:BLOCK_ASSOCIATION]->(new_block)
38
44
  ON CREATE SET r.firstseen = timestamp()
39
- SET r.lastupdated = $update_tag""")
45
+ SET r.lastupdated = $update_tag""",
46
+ )
40
47
 
41
48
  BLOCK_CIDR = "CidrBlock"
42
49
  STATE_NAME = "CidrBlockState"
@@ -53,12 +60,19 @@ def _get_cidr_association_statement(block_type: str) -> str:
53
60
  else:
54
61
  raise ValueError(f"Unsupported block type specified - {block_type}")
55
62
 
56
- return INGEST_CIDR_TEMPLATE.safe_substitute(block_label=BLOCK_TYPE, block_cidr=BLOCK_CIDR, state_name=STATE_NAME)
63
+ return INGEST_CIDR_TEMPLATE.safe_substitute(
64
+ block_label=BLOCK_TYPE,
65
+ block_cidr=BLOCK_CIDR,
66
+ state_name=STATE_NAME,
67
+ )
57
68
 
58
69
 
59
70
  @timeit
60
71
  def load_cidr_association_set(
61
- neo4j_session: neo4j.Session, vpc_id: str, vpc_data: Dict, block_type: str,
72
+ neo4j_session: neo4j.Session,
73
+ vpc_id: str,
74
+ vpc_data: Dict,
75
+ block_type: str,
62
76
  update_tag: int,
63
77
  ) -> None:
64
78
  ingest_statement = _get_cidr_association_statement(block_type)
@@ -78,7 +92,10 @@ def load_cidr_association_set(
78
92
 
79
93
  @timeit
80
94
  def load_ec2_vpcs(
81
- neo4j_session: neo4j.Session, data: List[Dict], region: str, current_aws_account_id: str,
95
+ neo4j_session: neo4j.Session,
96
+ data: List[Dict],
97
+ region: str,
98
+ current_aws_account_id: str,
82
99
  update_tag: int,
83
100
  ) -> None:
84
101
  # https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-vpcs.html
@@ -161,16 +178,24 @@ def load_ec2_vpcs(
161
178
 
162
179
  @timeit
163
180
  def cleanup_ec2_vpcs(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
164
- run_cleanup_job('aws_import_vpc_cleanup.json', neo4j_session, common_job_parameters)
181
+ run_cleanup_job("aws_import_vpc_cleanup.json", neo4j_session, common_job_parameters)
165
182
 
166
183
 
167
184
  @timeit
168
185
  def sync_vpc(
169
- neo4j_session: neo4j.Session, boto3_session: boto3.session.Session, regions: List[str], current_aws_account_id: str,
170
- update_tag: int, common_job_parameters: Dict,
186
+ neo4j_session: neo4j.Session,
187
+ boto3_session: boto3.session.Session,
188
+ regions: List[str],
189
+ current_aws_account_id: str,
190
+ update_tag: int,
191
+ common_job_parameters: Dict,
171
192
  ) -> None:
172
193
  for region in regions:
173
- logger.info("Syncing EC2 VPC for region '%s' in account '%s'.", region, current_aws_account_id)
194
+ logger.info(
195
+ "Syncing EC2 VPC for region '%s' in account '%s'.",
196
+ region,
197
+ current_aws_account_id,
198
+ )
174
199
  data = get_ec2_vpcs(boto3_session, region)
175
200
  load_ec2_vpcs(neo4j_session, data, region, current_aws_account_id, update_tag)
176
201
  cleanup_ec2_vpcs(neo4j_session, common_job_parameters)
@@ -5,25 +5,36 @@ from typing import List
5
5
  import boto3
6
6
  import neo4j
7
7
 
8
- from .util import get_botocore_config
9
8
  from cartography.util import aws_handle_regions
10
9
  from cartography.util import run_cleanup_job
11
10
  from cartography.util import timeit
12
11
 
12
+ from .util import get_botocore_config
13
+
13
14
  logger = logging.getLogger(__name__)
14
15
 
15
16
 
16
17
  @timeit
17
18
  @aws_handle_regions
18
- def get_vpc_peerings_data(boto3_session: boto3.session.Session, region: str) -> List[Dict]:
19
- client = boto3_session.client('ec2', region_name=region, config=get_botocore_config())
20
- return client.describe_vpc_peering_connections()['VpcPeeringConnections']
19
+ def get_vpc_peerings_data(
20
+ boto3_session: boto3.session.Session,
21
+ region: str,
22
+ ) -> List[Dict]:
23
+ client = boto3_session.client(
24
+ "ec2",
25
+ region_name=region,
26
+ config=get_botocore_config(),
27
+ )
28
+ return client.describe_vpc_peering_connections()["VpcPeeringConnections"]
21
29
 
22
30
 
23
31
  @timeit
24
32
  def load_vpc_peerings(
25
- neo4j_session: neo4j.Session, data: List[Dict], region: str,
26
- aws_account_id: str, update_tag: int,
33
+ neo4j_session: neo4j.Session,
34
+ data: List[Dict],
35
+ region: str,
36
+ aws_account_id: str,
37
+ update_tag: int,
27
38
  ) -> None:
28
39
  ingest_vpc_peerings = """
29
40
  UNWIND $vpc_peerings AS vpc_peering
@@ -77,15 +88,21 @@ def load_vpc_peerings(
77
88
  """
78
89
 
79
90
  neo4j_session.run(
80
- ingest_vpc_peerings, vpc_peerings=data, update_tag=update_tag,
81
- region=region, aws_account_id=aws_account_id,
91
+ ingest_vpc_peerings,
92
+ vpc_peerings=data,
93
+ update_tag=update_tag,
94
+ region=region,
95
+ aws_account_id=aws_account_id,
82
96
  )
83
97
 
84
98
 
85
99
  @timeit
86
100
  def load_accepter_cidrs(
87
- neo4j_session: neo4j.Session, data: List[Dict], region: str,
88
- aws_account_id: str, update_tag: int,
101
+ neo4j_session: neo4j.Session,
102
+ data: List[Dict],
103
+ region: str,
104
+ aws_account_id: str,
105
+ update_tag: int,
89
106
  ) -> None:
90
107
 
91
108
  ingest_accepter_cidr = """
@@ -110,15 +127,21 @@ def load_accepter_cidrs(
110
127
  """
111
128
 
112
129
  neo4j_session.run(
113
- ingest_accepter_cidr, vpc_peerings=data, update_tag=update_tag,
114
- region=region, aws_account_id=aws_account_id,
130
+ ingest_accepter_cidr,
131
+ vpc_peerings=data,
132
+ update_tag=update_tag,
133
+ region=region,
134
+ aws_account_id=aws_account_id,
115
135
  )
116
136
 
117
137
 
118
138
  @timeit
119
139
  def load_requester_cidrs(
120
- neo4j_session: neo4j.Session, data: List[Dict], region: str,
121
- aws_account_id: str, update_tag: int,
140
+ neo4j_session: neo4j.Session,
141
+ data: List[Dict],
142
+ region: str,
143
+ aws_account_id: str,
144
+ update_tag: int,
122
145
  ) -> None:
123
146
 
124
147
  ingest_requester_cidr = """
@@ -143,25 +166,61 @@ def load_requester_cidrs(
143
166
  """
144
167
 
145
168
  neo4j_session.run(
146
- ingest_requester_cidr, vpc_peerings=data, update_tag=update_tag,
147
- region=region, aws_account_id=aws_account_id,
169
+ ingest_requester_cidr,
170
+ vpc_peerings=data,
171
+ update_tag=update_tag,
172
+ region=region,
173
+ aws_account_id=aws_account_id,
148
174
  )
149
175
 
150
176
 
151
177
  @timeit
152
- def cleanup_vpc_peerings(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
153
- run_cleanup_job('aws_import_vpc_peering_cleanup.json', neo4j_session, common_job_parameters)
178
+ def cleanup_vpc_peerings(
179
+ neo4j_session: neo4j.Session,
180
+ common_job_parameters: Dict,
181
+ ) -> None:
182
+ run_cleanup_job(
183
+ "aws_import_vpc_peering_cleanup.json",
184
+ neo4j_session,
185
+ common_job_parameters,
186
+ )
154
187
 
155
188
 
156
189
  @timeit
157
190
  def sync_vpc_peerings(
158
- neo4j_session: neo4j.Session, boto3_session: boto3.session.Session, regions: List[str],
159
- current_aws_account_id: str, update_tag: int, common_job_parameters: Dict,
191
+ neo4j_session: neo4j.Session,
192
+ boto3_session: boto3.session.Session,
193
+ regions: List[str],
194
+ current_aws_account_id: str,
195
+ update_tag: int,
196
+ common_job_parameters: Dict,
160
197
  ) -> None:
161
198
  for region in regions:
162
- logger.debug("Syncing EC2 VPC peering for region '%s' in account '%s'.", region, current_aws_account_id)
199
+ logger.debug(
200
+ "Syncing EC2 VPC peering for region '%s' in account '%s'.",
201
+ region,
202
+ current_aws_account_id,
203
+ )
163
204
  data = get_vpc_peerings_data(boto3_session, region)
164
- load_vpc_peerings(neo4j_session, data, region, current_aws_account_id, update_tag)
165
- load_accepter_cidrs(neo4j_session, data, region, current_aws_account_id, update_tag)
166
- load_requester_cidrs(neo4j_session, data, region, current_aws_account_id, update_tag)
205
+ load_vpc_peerings(
206
+ neo4j_session,
207
+ data,
208
+ region,
209
+ current_aws_account_id,
210
+ update_tag,
211
+ )
212
+ load_accepter_cidrs(
213
+ neo4j_session,
214
+ data,
215
+ region,
216
+ current_aws_account_id,
217
+ update_tag,
218
+ )
219
+ load_requester_cidrs(
220
+ neo4j_session,
221
+ data,
222
+ region,
223
+ current_aws_account_id,
224
+ update_tag,
225
+ )
167
226
  cleanup_vpc_peerings(neo4j_session, common_job_parameters)
@@ -18,33 +18,48 @@ logger = logging.getLogger(__name__)
18
18
 
19
19
  @timeit
20
20
  @aws_handle_regions
21
- def get_ecr_repositories(boto3_session: boto3.session.Session, region: str) -> List[Dict]:
21
+ def get_ecr_repositories(
22
+ boto3_session: boto3.session.Session,
23
+ region: str,
24
+ ) -> List[Dict]:
22
25
  logger.info("Getting ECR repositories for region '%s'.", region)
23
- client = boto3_session.client('ecr', region_name=region)
24
- paginator = client.get_paginator('describe_repositories')
26
+ client = boto3_session.client("ecr", region_name=region)
27
+ paginator = client.get_paginator("describe_repositories")
25
28
  ecr_repositories: List[Dict] = []
26
29
  for page in paginator.paginate():
27
- ecr_repositories.extend(page['repositories'])
30
+ ecr_repositories.extend(page["repositories"])
28
31
  return ecr_repositories
29
32
 
30
33
 
31
34
  @timeit
32
35
  @aws_handle_regions
33
- def get_ecr_repository_images(boto3_session: boto3.session.Session, region: str, repository_name: str) -> List[Dict]:
34
- logger.debug("Getting ECR images in repository '%s' for region '%s'.", repository_name, region)
35
- client = boto3_session.client('ecr', region_name=region)
36
- list_paginator = client.get_paginator('list_images')
36
+ def get_ecr_repository_images(
37
+ boto3_session: boto3.session.Session, region: str, repository_name: str
38
+ ) -> List[Dict]:
39
+ logger.debug(
40
+ "Getting ECR images in repository '%s' for region '%s'.",
41
+ repository_name,
42
+ region,
43
+ )
44
+ client = boto3_session.client("ecr", region_name=region)
45
+ list_paginator = client.get_paginator("list_images")
37
46
  ecr_repository_images: List[Dict] = []
38
47
  for page in list_paginator.paginate(repositoryName=repository_name):
39
- image_ids = page['imageIds']
48
+ image_ids = page["imageIds"]
40
49
  if not image_ids:
41
50
  continue
42
- describe_paginator = client.get_paginator('describe_images')
43
- describe_response = describe_paginator.paginate(repositoryName=repository_name, imageIds=image_ids)
51
+ describe_paginator = client.get_paginator("describe_images")
52
+ describe_response = describe_paginator.paginate(
53
+ repositoryName=repository_name, imageIds=image_ids
54
+ )
44
55
  for response in describe_response:
45
- image_details = response['imageDetails']
56
+ image_details = response["imageDetails"]
46
57
  image_details = [
47
- {**detail, 'imageTag': detail['imageTags'][0]} if detail.get('imageTags') else detail
58
+ (
59
+ {**detail, "imageTag": detail["imageTags"][0]}
60
+ if detail.get("imageTags")
61
+ else detail
62
+ )
48
63
  for detail in image_details
49
64
  ]
50
65
  ecr_repository_images.extend(image_details)
@@ -53,7 +68,10 @@ def get_ecr_repository_images(boto3_session: boto3.session.Session, region: str,
53
68
 
54
69
  @timeit
55
70
  def load_ecr_repositories(
56
- neo4j_session: neo4j.Session, repos: List[Dict], region: str, current_aws_account_id: str,
71
+ neo4j_session: neo4j.Session,
72
+ repos: List[Dict],
73
+ region: str,
74
+ current_aws_account_id: str,
57
75
  aws_update_tag: int,
58
76
  ) -> None:
59
77
  query = """
@@ -73,7 +91,9 @@ def load_ecr_repositories(
73
91
  ON CREATE SET r.firstseen = timestamp()
74
92
  SET r.lastupdated = $aws_update_tag
75
93
  """
76
- logger.info(f"Loading {len(repos)} ECR repositories for region {region} into graph.")
94
+ logger.info(
95
+ f"Loading {len(repos)} ECR repositories for region {region} into graph.",
96
+ )
77
97
  neo4j_session.run(
78
98
  query,
79
99
  Repositories=repos,
@@ -91,21 +111,23 @@ def transform_ecr_repository_images(repo_data: Dict) -> List[Dict]:
91
111
  repo_images_list = []
92
112
  for repo_uri, repo_images in repo_data.items():
93
113
  for img in repo_images:
94
- if 'imageDigest' in img and img['imageDigest']:
95
- img['repo_uri'] = repo_uri
114
+ if "imageDigest" in img and img["imageDigest"]:
115
+ img["repo_uri"] = repo_uri
96
116
  repo_images_list.append(img)
97
117
  else:
98
118
  logger.warning(
99
119
  "Repo %s has an image that has no imageDigest. Its tag is %s. Continuing on.",
100
120
  repo_uri,
101
- img.get('imageTag'),
121
+ img.get("imageTag"),
102
122
  )
103
123
 
104
124
  return repo_images_list
105
125
 
106
126
 
107
127
  def _load_ecr_repo_img_tx(
108
- tx: neo4j.Transaction, repo_images_list: List[Dict], aws_update_tag: int,
128
+ tx: neo4j.Transaction,
129
+ repo_images_list: List[Dict],
130
+ aws_update_tag: int,
109
131
  region: str,
110
132
  ) -> None:
111
133
  query = """
@@ -139,23 +161,37 @@ def _load_ecr_repo_img_tx(
139
161
  ON CREATE SET r2.firstseen = timestamp()
140
162
  SET r2.lastupdated = $aws_update_tag
141
163
  """
142
- tx.run(query, RepoList=repo_images_list, Region=region, aws_update_tag=aws_update_tag)
164
+ tx.run(
165
+ query,
166
+ RepoList=repo_images_list,
167
+ Region=region,
168
+ aws_update_tag=aws_update_tag,
169
+ )
143
170
 
144
171
 
145
172
  @timeit
146
173
  def load_ecr_repository_images(
147
- neo4j_session: neo4j.Session, repo_images_list: List[Dict], region: str,
174
+ neo4j_session: neo4j.Session,
175
+ repo_images_list: List[Dict],
176
+ region: str,
148
177
  aws_update_tag: int,
149
178
  ) -> None:
150
- logger.info(f"Loading {len(repo_images_list)} ECR repository images in {region} into graph.")
179
+ logger.info(
180
+ f"Loading {len(repo_images_list)} ECR repository images in {region} into graph.",
181
+ )
151
182
  for repo_image_batch in batch(repo_images_list, size=10000):
152
- neo4j_session.write_transaction(_load_ecr_repo_img_tx, repo_image_batch, aws_update_tag, region)
183
+ neo4j_session.write_transaction(
184
+ _load_ecr_repo_img_tx,
185
+ repo_image_batch,
186
+ aws_update_tag,
187
+ region,
188
+ )
153
189
 
154
190
 
155
191
  @timeit
156
192
  def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
157
193
  logger.debug("Running ECR cleanup job.")
158
- run_cleanup_job('aws_import_ecr_cleanup.json', neo4j_session, common_job_parameters)
194
+ run_cleanup_job("aws_import_ecr_cleanup.json", neo4j_session, common_job_parameters)
159
195
 
160
196
 
161
197
  def _get_image_data(
@@ -163,15 +199,21 @@ def _get_image_data(
163
199
  region: str,
164
200
  repositories: List[Dict[str, Any]],
165
201
  ) -> Dict[str, Any]:
166
- '''
202
+ """
167
203
  Given a list of repositories, get the image data for each repository,
168
204
  return as a mapping from repositoryUri to image object
169
- '''
205
+ """
170
206
  image_data = {}
171
207
 
172
208
  async def async_get_images(repo: Dict[str, Any]) -> None:
173
- repo_image_obj = await to_asynchronous(get_ecr_repository_images, boto3_session, region, repo['repositoryName'])
174
- image_data[repo['repositoryUri']] = repo_image_obj
209
+ repo_image_obj = await to_asynchronous(
210
+ get_ecr_repository_images,
211
+ boto3_session,
212
+ region,
213
+ repo["repositoryName"],
214
+ )
215
+ image_data[repo["repositoryUri"]] = repo_image_obj
216
+
175
217
  to_synchronous(*[async_get_images(repo) for repo in repositories])
176
218
 
177
219
  return image_data
@@ -179,15 +221,29 @@ def _get_image_data(
179
221
 
180
222
  @timeit
181
223
  def sync(
182
- neo4j_session: neo4j.Session, boto3_session: boto3.session.Session, regions: List[str], current_aws_account_id: str,
183
- update_tag: int, common_job_parameters: Dict,
224
+ neo4j_session: neo4j.Session,
225
+ boto3_session: boto3.session.Session,
226
+ regions: List[str],
227
+ current_aws_account_id: str,
228
+ update_tag: int,
229
+ common_job_parameters: Dict,
184
230
  ) -> None:
185
231
  for region in regions:
186
- logger.info("Syncing ECR for region '%s' in account '%s'.", region, current_aws_account_id)
232
+ logger.info(
233
+ "Syncing ECR for region '%s' in account '%s'.",
234
+ region,
235
+ current_aws_account_id,
236
+ )
187
237
  image_data = {}
188
238
  repositories = get_ecr_repositories(boto3_session, region)
189
239
  image_data = _get_image_data(boto3_session, region, repositories)
190
- load_ecr_repositories(neo4j_session, repositories, region, current_aws_account_id, update_tag)
240
+ load_ecr_repositories(
241
+ neo4j_session,
242
+ repositories,
243
+ region,
244
+ current_aws_account_id,
245
+ update_tag,
246
+ )
191
247
  repo_images_list = transform_ecr_repository_images(image_data)
192
248
  load_ecr_repository_images(neo4j_session, repo_images_list, region, update_tag)
193
249
  cleanup(neo4j_session, common_job_parameters)