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
@@ -24,8 +24,8 @@ stat_handler = get_stats_client(__name__)
24
24
 
25
25
 
26
26
  class PolicyType(enum.Enum):
27
- managed = 'managed'
28
- inline = 'inline'
27
+ managed = "managed"
28
+ inline = "inline"
29
29
 
30
30
 
31
31
  def get_policy_name_from_arn(arn: str) -> str:
@@ -34,49 +34,66 @@ def get_policy_name_from_arn(arn: str) -> str:
34
34
 
35
35
  @timeit
36
36
  def get_group_policies(boto3_session: boto3.session.Session, group_name: str) -> Dict:
37
- client = boto3_session.client('iam')
38
- paginator = client.get_paginator('list_group_policies')
37
+ client = boto3_session.client("iam")
38
+ paginator = client.get_paginator("list_group_policies")
39
39
  policy_names: List[Dict] = []
40
40
  for page in paginator.paginate(GroupName=group_name):
41
- policy_names.extend(page['PolicyNames'])
42
- return {'PolicyNames': policy_names}
41
+ policy_names.extend(page["PolicyNames"])
42
+ return {"PolicyNames": policy_names}
43
43
 
44
44
 
45
45
  @timeit
46
46
  def get_group_policy_info(
47
- boto3_session: boto3.session.Session, group_name: str, policy_name: str,
47
+ boto3_session: boto3.session.Session,
48
+ group_name: str,
49
+ policy_name: str,
48
50
  ) -> Any:
49
- client = boto3_session.client('iam')
51
+ client = boto3_session.client("iam")
50
52
  return client.get_group_policy(GroupName=group_name, PolicyName=policy_name)
51
53
 
52
54
 
53
55
  @timeit
54
- def get_group_membership_data(boto3_session: boto3.session.Session, group_name: str) -> Dict:
55
- client = boto3_session.client('iam')
56
+ def get_group_membership_data(
57
+ boto3_session: boto3.session.Session,
58
+ group_name: str,
59
+ ) -> Dict:
60
+ client = boto3_session.client("iam")
56
61
  try:
57
62
  memberships = client.get_group(GroupName=group_name)
58
63
  return memberships
59
64
  except client.exceptions.NoSuchEntityException:
60
65
  # Avoid crashing the sync
61
- logger.warning("client.get_group(GroupName='%s') failed with NoSuchEntityException; skipping.", group_name)
66
+ logger.warning(
67
+ "client.get_group(GroupName='%s') failed with NoSuchEntityException; skipping.",
68
+ group_name,
69
+ )
62
70
  return {}
63
71
 
64
72
 
65
73
  @timeit
66
- def get_group_policy_data(boto3_session: boto3.session.Session, group_list: List[Dict]) -> Dict:
67
- resource_client = boto3_session.resource('iam')
74
+ def get_group_policy_data(
75
+ boto3_session: boto3.session.Session,
76
+ group_list: List[Dict],
77
+ ) -> Dict:
78
+ resource_client = boto3_session.resource("iam")
68
79
  policies = {}
69
80
  for group in group_list:
70
81
  name = group["GroupName"]
71
82
  arn = group["Arn"]
72
83
  resource_group = resource_client.Group(name)
73
- policies[arn] = policies[arn] = {p.name: p.policy_document["Statement"] for p in resource_group.policies.all()}
84
+ policies[arn] = policies[arn] = {
85
+ p.name: p.policy_document["Statement"]
86
+ for p in resource_group.policies.all()
87
+ }
74
88
  return policies
75
89
 
76
90
 
77
91
  @timeit
78
- def get_group_managed_policy_data(boto3_session: boto3.session.Session, group_list: List[Dict]) -> Dict:
79
- resource_client = boto3_session.resource('iam')
92
+ def get_group_managed_policy_data(
93
+ boto3_session: boto3.session.Session,
94
+ group_list: List[Dict],
95
+ ) -> Dict:
96
+ resource_client = boto3_session.resource("iam")
80
97
  policies = {}
81
98
  for group in group_list:
82
99
  name = group["GroupName"]
@@ -90,15 +107,21 @@ def get_group_managed_policy_data(boto3_session: boto3.session.Session, group_li
90
107
 
91
108
 
92
109
  @timeit
93
- def get_user_policy_data(boto3_session: boto3.session.Session, user_list: List[Dict]) -> Dict:
94
- resource_client = boto3_session.resource('iam')
110
+ def get_user_policy_data(
111
+ boto3_session: boto3.session.Session,
112
+ user_list: List[Dict],
113
+ ) -> Dict:
114
+ resource_client = boto3_session.resource("iam")
95
115
  policies = {}
96
116
  for user in user_list:
97
117
  name = user["UserName"]
98
118
  arn = user["Arn"]
99
119
  resource_user = resource_client.User(name)
100
120
  try:
101
- policies[arn] = {p.name: p.policy_document["Statement"] for p in resource_user.policies.all()}
121
+ policies[arn] = {
122
+ p.name: p.policy_document["Statement"]
123
+ for p in resource_user.policies.all()
124
+ }
102
125
  except resource_client.meta.client.exceptions.NoSuchEntityException:
103
126
  logger.warning(
104
127
  f"Could not get policies for user {name} due to NoSuchEntityException; skipping.",
@@ -107,8 +130,11 @@ def get_user_policy_data(boto3_session: boto3.session.Session, user_list: List[D
107
130
 
108
131
 
109
132
  @timeit
110
- def get_user_managed_policy_data(boto3_session: boto3.session.Session, user_list: List[Dict]) -> Dict:
111
- resource_client = boto3_session.resource('iam')
133
+ def get_user_managed_policy_data(
134
+ boto3_session: boto3.session.Session,
135
+ user_list: List[Dict],
136
+ ) -> Dict:
137
+ resource_client = boto3_session.resource("iam")
112
138
  policies = {}
113
139
  for user in user_list:
114
140
  name = user["UserName"]
@@ -127,15 +153,21 @@ def get_user_managed_policy_data(boto3_session: boto3.session.Session, user_list
127
153
 
128
154
 
129
155
  @timeit
130
- def get_role_policy_data(boto3_session: boto3.session.Session, role_list: List[Dict]) -> Dict:
131
- resource_client = boto3_session.resource('iam')
156
+ def get_role_policy_data(
157
+ boto3_session: boto3.session.Session,
158
+ role_list: List[Dict],
159
+ ) -> Dict:
160
+ resource_client = boto3_session.resource("iam")
132
161
  policies = {}
133
162
  for role in role_list:
134
163
  name = role["RoleName"]
135
164
  arn = role["Arn"]
136
165
  resource_role = resource_client.Role(name)
137
166
  try:
138
- policies[arn] = {p.name: p.policy_document["Statement"] for p in resource_role.policies.all()}
167
+ policies[arn] = {
168
+ p.name: p.policy_document["Statement"]
169
+ for p in resource_role.policies.all()
170
+ }
139
171
  except resource_client.meta.client.exceptions.NoSuchEntityException:
140
172
  logger.warning(
141
173
  f"Could not get policies for role {name} due to NoSuchEntityException; skipping.",
@@ -144,8 +176,11 @@ def get_role_policy_data(boto3_session: boto3.session.Session, role_list: List[D
144
176
 
145
177
 
146
178
  @timeit
147
- def get_role_managed_policy_data(boto3_session: boto3.session.Session, role_list: List[Dict]) -> Dict:
148
- resource_client = boto3_session.resource('iam')
179
+ def get_role_managed_policy_data(
180
+ boto3_session: boto3.session.Session,
181
+ role_list: List[Dict],
182
+ ) -> Dict:
183
+ resource_client = boto3_session.resource("iam")
149
184
  policies = {}
150
185
  for role in role_list:
151
186
  name = role["RoleName"]
@@ -165,8 +200,8 @@ def get_role_managed_policy_data(boto3_session: boto3.session.Session, role_list
165
200
 
166
201
  @timeit
167
202
  def get_role_tags(boto3_session: boto3.session.Session) -> List[Dict]:
168
- role_list = get_role_list_data(boto3_session)['Roles']
169
- resource_client = boto3_session.resource('iam')
203
+ role_list = get_role_list_data(boto3_session)["Roles"]
204
+ resource_client = boto3_session.resource("iam")
170
205
  role_tag_data: List[Dict] = []
171
206
  for role in role_list:
172
207
  name = role["RoleName"]
@@ -177,8 +212,8 @@ def get_role_tags(boto3_session: boto3.session.Session) -> List[Dict]:
177
212
  continue
178
213
 
179
214
  tag_data = {
180
- 'ResourceARN': role_arn,
181
- 'Tags': resource_role.tags,
215
+ "ResourceARN": role_arn,
216
+ "Tags": resource_role.tags,
182
217
  }
183
218
  role_tag_data.append(tag_data)
184
219
 
@@ -187,38 +222,41 @@ def get_role_tags(boto3_session: boto3.session.Session) -> List[Dict]:
187
222
 
188
223
  @timeit
189
224
  def get_user_list_data(boto3_session: boto3.session.Session) -> Dict:
190
- client = boto3_session.client('iam')
225
+ client = boto3_session.client("iam")
191
226
 
192
- paginator = client.get_paginator('list_users')
227
+ paginator = client.get_paginator("list_users")
193
228
  users: List[Dict] = []
194
229
  for page in paginator.paginate():
195
- users.extend(page['Users'])
196
- return {'Users': users}
230
+ users.extend(page["Users"])
231
+ return {"Users": users}
197
232
 
198
233
 
199
234
  @timeit
200
235
  def get_group_list_data(boto3_session: boto3.session.Session) -> Dict:
201
- client = boto3_session.client('iam')
202
- paginator = client.get_paginator('list_groups')
236
+ client = boto3_session.client("iam")
237
+ paginator = client.get_paginator("list_groups")
203
238
  groups: List[Dict] = []
204
239
  for page in paginator.paginate():
205
- groups.extend(page['Groups'])
206
- return {'Groups': groups}
240
+ groups.extend(page["Groups"])
241
+ return {"Groups": groups}
207
242
 
208
243
 
209
244
  @timeit
210
245
  def get_role_list_data(boto3_session: boto3.session.Session) -> Dict:
211
- client = boto3_session.client('iam')
212
- paginator = client.get_paginator('list_roles')
246
+ client = boto3_session.client("iam")
247
+ paginator = client.get_paginator("list_roles")
213
248
  roles: List[Dict] = []
214
249
  for page in paginator.paginate():
215
- roles.extend(page['Roles'])
216
- return {'Roles': roles}
250
+ roles.extend(page["Roles"])
251
+ return {"Roles": roles}
217
252
 
218
253
 
219
254
  @timeit
220
- def get_account_access_key_data(boto3_session: boto3.session.Session, username: str) -> Dict:
221
- client = boto3_session.client('iam')
255
+ def get_account_access_key_data(
256
+ boto3_session: boto3.session.Session,
257
+ username: str,
258
+ ) -> Dict:
259
+ client = boto3_session.client("iam")
222
260
  # NOTE we can get away without using a paginator here because users are limited to two access keys
223
261
  access_keys: Dict = {}
224
262
  try:
@@ -228,22 +266,25 @@ def get_account_access_key_data(boto3_session: boto3.session.Session, username:
228
266
  f"Could not get access key for user {username} due to NoSuchEntityException; skipping.",
229
267
  )
230
268
  return access_keys
231
- for access_key in access_keys['AccessKeyMetadata']:
232
- access_key_id = access_key['AccessKeyId']
269
+ for access_key in access_keys["AccessKeyMetadata"]:
270
+ access_key_id = access_key["AccessKeyId"]
233
271
  last_used_info = client.get_access_key_last_used(
234
272
  AccessKeyId=access_key_id,
235
- )['AccessKeyLastUsed']
273
+ )["AccessKeyLastUsed"]
236
274
  # only LastUsedDate may be null
237
275
  # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/iam/client/get_access_key_last_used.html
238
- access_key['LastUsedDate'] = last_used_info.get('LastUsedDate')
239
- access_key['LastUsedService'] = last_used_info['ServiceName']
240
- access_key['LastUsedRegion'] = last_used_info['Region']
276
+ access_key["LastUsedDate"] = last_used_info.get("LastUsedDate")
277
+ access_key["LastUsedService"] = last_used_info["ServiceName"]
278
+ access_key["LastUsedRegion"] = last_used_info["Region"]
241
279
  return access_keys
242
280
 
243
281
 
244
282
  @timeit
245
283
  def load_users(
246
- neo4j_session: neo4j.Session, users: List[Dict], current_aws_account_id: str, aws_update_tag: int,
284
+ neo4j_session: neo4j.Session,
285
+ users: List[Dict],
286
+ current_aws_account_id: str,
287
+ aws_update_tag: int,
247
288
  ) -> None:
248
289
  ingest_user = """
249
290
  MERGE (unode:AWSUser{arn: $ARN})
@@ -274,7 +315,10 @@ def load_users(
274
315
 
275
316
  @timeit
276
317
  def load_groups(
277
- neo4j_session: neo4j.Session, groups: List[Dict], current_aws_account_id: str, aws_update_tag: int,
318
+ neo4j_session: neo4j.Session,
319
+ groups: List[Dict],
320
+ current_aws_account_id: str,
321
+ aws_update_tag: int,
278
322
  ) -> None:
279
323
  ingest_group = """
280
324
  MERGE (gnode:AWSGroup{arn: $ARN})
@@ -317,7 +361,10 @@ def _parse_principal_entries(principal: Dict) -> List[Tuple[Any, Any]]:
317
361
 
318
362
  @timeit
319
363
  def load_roles(
320
- neo4j_session: neo4j.Session, roles: List[Dict], current_aws_account_id: str, aws_update_tag: int,
364
+ neo4j_session: neo4j.Session,
365
+ roles: List[Dict],
366
+ current_aws_account_id: str,
367
+ aws_update_tag: int,
321
368
  ) -> None:
322
369
  ingest_role = """
323
370
  MERGE (rnode:AWSPrincipal{arn: $Arn})
@@ -387,7 +434,7 @@ def load_roles(
387
434
  ingest_policy_statement,
388
435
  SpnArn=principal_value,
389
436
  SpnType=principal_type,
390
- RoleArn=role['Arn'],
437
+ RoleArn=role["Arn"],
391
438
  aws_update_tag=aws_update_tag,
392
439
  )
393
440
  spn_arn = get_account_from_arn(principal_value)
@@ -401,7 +448,11 @@ def load_roles(
401
448
 
402
449
 
403
450
  @timeit
404
- def load_group_memberships(neo4j_session: neo4j.Session, group_memberships: Dict, aws_update_tag: int) -> None:
451
+ def load_group_memberships(
452
+ neo4j_session: neo4j.Session,
453
+ group_memberships: Dict,
454
+ aws_update_tag: int,
455
+ ) -> None:
405
456
  ingest_membership = """
406
457
  MATCH (group:AWSGroup{arn: $GroupArn})
407
458
  WITH group
@@ -427,7 +478,10 @@ def load_group_memberships(neo4j_session: neo4j.Session, group_memberships: Dict
427
478
 
428
479
 
429
480
  @timeit
430
- def get_policies_for_principal(neo4j_session: neo4j.Session, principal_arn: str) -> Dict:
481
+ def get_policies_for_principal(
482
+ neo4j_session: neo4j.Session,
483
+ principal_arn: str,
484
+ ) -> Dict:
431
485
  get_policy_query = """
432
486
  MATCH
433
487
  (principal:AWSPrincipal{arn:$Arn})-[:POLICY]->
@@ -447,12 +501,17 @@ def get_policies_for_principal(neo4j_session: neo4j.Session, principal_arn: str)
447
501
 
448
502
  @timeit
449
503
  def sync_assumerole_relationships(
450
- neo4j_session: neo4j.Session, current_aws_account_id: str, aws_update_tag: int,
504
+ neo4j_session: neo4j.Session,
505
+ current_aws_account_id: str,
506
+ aws_update_tag: int,
451
507
  common_job_parameters: Dict,
452
508
  ) -> None:
453
509
  # Must be called after load_role
454
510
  # Computes and syncs the STS_ASSUME_ROLE allow relationship
455
- logger.info("Syncing assume role mappings for account '%s'.", current_aws_account_id)
511
+ logger.info(
512
+ "Syncing assume role mappings for account '%s'.",
513
+ current_aws_account_id,
514
+ )
456
515
  query_potential_matches = """
457
516
  MATCH (:AWSAccount{id:$AccountId})-[:RESOURCE]->(target:AWSRole)-[:TRUSTS_AWS_PRINCIPAL]->(source:AWSPrincipal)
458
517
  WHERE NOT source.arn ENDS WITH 'root'
@@ -487,14 +546,18 @@ def sync_assumerole_relationships(
487
546
  aws_update_tag=aws_update_tag,
488
547
  )
489
548
  run_cleanup_job(
490
- 'aws_import_roles_policy_cleanup.json',
549
+ "aws_import_roles_policy_cleanup.json",
491
550
  neo4j_session,
492
551
  common_job_parameters,
493
552
  )
494
553
 
495
554
 
496
555
  @timeit
497
- def load_user_access_keys(neo4j_session: neo4j.Session, user_access_keys: Dict, aws_update_tag: int) -> None:
556
+ def load_user_access_keys(
557
+ neo4j_session: neo4j.Session,
558
+ user_access_keys: Dict,
559
+ aws_update_tag: int,
560
+ ) -> None:
498
561
  # TODO change the node label to reflect that this is a user access key, not an account access key
499
562
  ingest_account_key = """
500
563
  MATCH (user:AWSUser{arn: $UserARN})
@@ -514,16 +577,16 @@ def load_user_access_keys(neo4j_session: neo4j.Session, user_access_keys: Dict,
514
577
 
515
578
  for arn, access_keys in user_access_keys.items():
516
579
  for key in access_keys["AccessKeyMetadata"]:
517
- if key.get('AccessKeyId'):
580
+ if key.get("AccessKeyId"):
518
581
  neo4j_session.run(
519
582
  ingest_account_key,
520
583
  UserARN=arn,
521
- AccessKeyId=key['AccessKeyId'],
522
- CreateDate=str(key['CreateDate']),
523
- Status=key['Status'],
524
- LastUsedDate=key['LastUsedDate'],
525
- LastUsedService=key['LastUsedService'],
526
- LastUsedRegion=key['LastUsedRegion'],
584
+ AccessKeyId=key["AccessKeyId"],
585
+ CreateDate=str(key["CreateDate"]),
586
+ Status=key["Status"],
587
+ LastUsedDate=key["LastUsedDate"],
588
+ LastUsedService=key["LastUsedService"],
589
+ LastUsedRegion=key["LastUsedRegion"],
527
590
  aws_update_tag=aws_update_tag,
528
591
  )
529
592
 
@@ -561,14 +624,23 @@ def _transform_policy_statements(statements: Any, policy_id: str) -> List[Dict]:
561
624
 
562
625
  def transform_policy_data(policy_map: Dict, policy_type: str) -> None:
563
626
  for principal_arn, policy_statement_map in policy_map.items():
564
- logger.debug(f"Transforming IAM {policy_type} policies for principal {principal_arn}")
627
+ logger.debug(
628
+ f"Transforming IAM {policy_type} policies for principal {principal_arn}",
629
+ )
565
630
  for policy_key, statements in policy_statement_map.items():
566
- policy_id = transform_policy_id(
567
- principal_arn,
568
- policy_type,
569
- policy_key,
570
- ) if policy_type == PolicyType.inline.value else policy_key
571
- policy_statement_map[policy_key] = _transform_policy_statements(statements, policy_id)
631
+ policy_id = (
632
+ transform_policy_id(
633
+ principal_arn,
634
+ policy_type,
635
+ policy_key,
636
+ )
637
+ if policy_type == PolicyType.inline.value
638
+ else policy_key
639
+ )
640
+ policy_statement_map[policy_key] = _transform_policy_statements(
641
+ statements,
642
+ policy_id,
643
+ )
572
644
 
573
645
 
574
646
  def transform_policy_id(principal_arn: str, policy_type: str, name: str) -> str:
@@ -576,7 +648,11 @@ def transform_policy_id(principal_arn: str, policy_type: str, name: str) -> str:
576
648
 
577
649
 
578
650
  def _load_policy_tx(
579
- tx: neo4j.Transaction, policy_id: str, policy_name: str, policy_type: str, principal_arn: str,
651
+ tx: neo4j.Transaction,
652
+ policy_id: str,
653
+ policy_name: str,
654
+ policy_type: str,
655
+ principal_arn: str,
580
656
  aws_update_tag: int,
581
657
  ) -> None:
582
658
  ingest_policy = """
@@ -603,15 +679,29 @@ def _load_policy_tx(
603
679
 
604
680
  @timeit
605
681
  def load_policy(
606
- neo4j_session: neo4j.Session, policy_id: str, policy_name: str, policy_type: str, principal_arn: str,
682
+ neo4j_session: neo4j.Session,
683
+ policy_id: str,
684
+ policy_name: str,
685
+ policy_type: str,
686
+ principal_arn: str,
607
687
  aws_update_tag: int,
608
688
  ) -> None:
609
- neo4j_session.write_transaction(_load_policy_tx, policy_id, policy_name, policy_type, principal_arn, aws_update_tag)
689
+ neo4j_session.write_transaction(
690
+ _load_policy_tx,
691
+ policy_id,
692
+ policy_name,
693
+ policy_type,
694
+ principal_arn,
695
+ aws_update_tag,
696
+ )
610
697
 
611
698
 
612
699
  @timeit
613
700
  def load_policy_statements(
614
- neo4j_session: neo4j.Session, policy_id: str, policy_name: str, statements: Any,
701
+ neo4j_session: neo4j.Session,
702
+ policy_id: str,
703
+ policy_name: str,
704
+ statements: Any,
615
705
  aws_update_tag: int,
616
706
  ) -> None:
617
707
  ingest_policy_statement = """
@@ -643,143 +733,258 @@ def load_policy_statements(
643
733
 
644
734
  @timeit
645
735
  def load_policy_data(
646
- neo4j_session: neo4j.Session,
647
- principal_policy_map: Dict[str, Dict[str, Any]],
648
- policy_type: str,
649
- aws_update_tag: int,
736
+ neo4j_session: neo4j.Session,
737
+ principal_policy_map: Dict[str, Dict[str, Any]],
738
+ policy_type: str,
739
+ aws_update_tag: int,
650
740
  ) -> None:
651
741
  for principal_arn, policy_statement_map in principal_policy_map.items():
652
742
  logger.debug(f"Loading policies for principal {principal_arn}")
653
743
  for policy_key, statements in policy_statement_map.items():
654
- policy_name = policy_key if policy_type == PolicyType.inline.value else get_policy_name_from_arn(policy_key)
655
- policy_id = transform_policy_id(
656
- principal_arn,
744
+ policy_name = (
745
+ policy_key
746
+ if policy_type == PolicyType.inline.value
747
+ else get_policy_name_from_arn(policy_key)
748
+ )
749
+ policy_id = (
750
+ transform_policy_id(
751
+ principal_arn,
752
+ policy_type,
753
+ policy_key,
754
+ )
755
+ if policy_type == PolicyType.inline.value
756
+ else policy_key
757
+ )
758
+ load_policy(
759
+ neo4j_session,
760
+ policy_id,
761
+ policy_name,
657
762
  policy_type,
658
- policy_key,
659
- ) if policy_type == PolicyType.inline.value else policy_key
660
- load_policy(neo4j_session, policy_id, policy_name, policy_type, principal_arn, aws_update_tag)
661
- load_policy_statements(neo4j_session, policy_id, policy_name, statements, aws_update_tag)
763
+ principal_arn,
764
+ aws_update_tag,
765
+ )
766
+ load_policy_statements(
767
+ neo4j_session,
768
+ policy_id,
769
+ policy_name,
770
+ statements,
771
+ aws_update_tag,
772
+ )
662
773
 
663
774
 
664
775
  @timeit
665
776
  def sync_users(
666
- neo4j_session: neo4j.Session, boto3_session: boto3.session.Session, current_aws_account_id: str,
667
- aws_update_tag: int, common_job_parameters: Dict,
777
+ neo4j_session: neo4j.Session,
778
+ boto3_session: boto3.session.Session,
779
+ current_aws_account_id: str,
780
+ aws_update_tag: int,
781
+ common_job_parameters: Dict,
668
782
  ) -> None:
669
783
  logger.info("Syncing IAM users for account '%s'.", current_aws_account_id)
670
784
  data = get_user_list_data(boto3_session)
671
- load_users(neo4j_session, data['Users'], current_aws_account_id, aws_update_tag)
785
+ load_users(neo4j_session, data["Users"], current_aws_account_id, aws_update_tag)
672
786
 
673
787
  sync_user_inline_policies(boto3_session, data, neo4j_session, aws_update_tag)
674
788
 
675
789
  sync_user_managed_policies(boto3_session, data, neo4j_session, aws_update_tag)
676
790
 
677
- run_cleanup_job('aws_import_users_cleanup.json', neo4j_session, common_job_parameters)
791
+ run_cleanup_job(
792
+ "aws_import_users_cleanup.json",
793
+ neo4j_session,
794
+ common_job_parameters,
795
+ )
678
796
 
679
797
 
680
798
  @timeit
681
799
  def sync_user_managed_policies(
682
- boto3_session: boto3.session.Session, data: Dict, neo4j_session: neo4j.Session,
800
+ boto3_session: boto3.session.Session,
801
+ data: Dict,
802
+ neo4j_session: neo4j.Session,
683
803
  aws_update_tag: int,
684
804
  ) -> None:
685
- managed_policy_data = get_user_managed_policy_data(boto3_session, data['Users'])
805
+ managed_policy_data = get_user_managed_policy_data(boto3_session, data["Users"])
686
806
  transform_policy_data(managed_policy_data, PolicyType.managed.value)
687
- load_policy_data(neo4j_session, managed_policy_data, PolicyType.managed.value, aws_update_tag)
807
+ load_policy_data(
808
+ neo4j_session,
809
+ managed_policy_data,
810
+ PolicyType.managed.value,
811
+ aws_update_tag,
812
+ )
688
813
 
689
814
 
690
815
  @timeit
691
816
  def sync_user_inline_policies(
692
- boto3_session: boto3.session.Session, data: Dict, neo4j_session: neo4j.Session,
817
+ boto3_session: boto3.session.Session,
818
+ data: Dict,
819
+ neo4j_session: neo4j.Session,
693
820
  aws_update_tag: int,
694
821
  ) -> None:
695
- policy_data = get_user_policy_data(boto3_session, data['Users'])
822
+ policy_data = get_user_policy_data(boto3_session, data["Users"])
696
823
  transform_policy_data(policy_data, PolicyType.inline.value)
697
- load_policy_data(neo4j_session, policy_data, PolicyType.inline.value, aws_update_tag)
824
+ load_policy_data(
825
+ neo4j_session,
826
+ policy_data,
827
+ PolicyType.inline.value,
828
+ aws_update_tag,
829
+ )
698
830
 
699
831
 
700
832
  @timeit
701
833
  def sync_groups(
702
- neo4j_session: neo4j.Session, boto3_session: boto3.session.Session, current_aws_account_id: str,
703
- aws_update_tag: int, common_job_parameters: Dict,
834
+ neo4j_session: neo4j.Session,
835
+ boto3_session: boto3.session.Session,
836
+ current_aws_account_id: str,
837
+ aws_update_tag: int,
838
+ common_job_parameters: Dict,
704
839
  ) -> None:
705
840
  logger.info("Syncing IAM groups for account '%s'.", current_aws_account_id)
706
841
  data = get_group_list_data(boto3_session)
707
- load_groups(neo4j_session, data['Groups'], current_aws_account_id, aws_update_tag)
842
+ load_groups(neo4j_session, data["Groups"], current_aws_account_id, aws_update_tag)
708
843
 
709
844
  sync_groups_inline_policies(boto3_session, data, neo4j_session, aws_update_tag)
710
845
 
711
846
  sync_group_managed_policies(boto3_session, data, neo4j_session, aws_update_tag)
712
847
 
713
- run_cleanup_job('aws_import_groups_cleanup.json', neo4j_session, common_job_parameters)
848
+ run_cleanup_job(
849
+ "aws_import_groups_cleanup.json",
850
+ neo4j_session,
851
+ common_job_parameters,
852
+ )
714
853
 
715
854
 
716
855
  def sync_group_managed_policies(
717
- boto3_session: boto3.session.Session, data: Dict, neo4j_session: neo4j.Session,
856
+ boto3_session: boto3.session.Session,
857
+ data: Dict,
858
+ neo4j_session: neo4j.Session,
718
859
  aws_update_tag: int,
719
860
  ) -> None:
720
861
  managed_policy_data = get_group_managed_policy_data(boto3_session, data["Groups"])
721
862
  transform_policy_data(managed_policy_data, PolicyType.managed.value)
722
- load_policy_data(neo4j_session, managed_policy_data, PolicyType.managed.value, aws_update_tag)
863
+ load_policy_data(
864
+ neo4j_session,
865
+ managed_policy_data,
866
+ PolicyType.managed.value,
867
+ aws_update_tag,
868
+ )
723
869
 
724
870
 
725
871
  def sync_groups_inline_policies(
726
- boto3_session: boto3.session.Session, data: Dict, neo4j_session: neo4j.Session,
872
+ boto3_session: boto3.session.Session,
873
+ data: Dict,
874
+ neo4j_session: neo4j.Session,
727
875
  aws_update_tag: int,
728
876
  ) -> None:
729
877
  policy_data = get_group_policy_data(boto3_session, data["Groups"])
730
878
  transform_policy_data(policy_data, PolicyType.inline.value)
731
- load_policy_data(neo4j_session, policy_data, PolicyType.inline.value, aws_update_tag)
879
+ load_policy_data(
880
+ neo4j_session,
881
+ policy_data,
882
+ PolicyType.inline.value,
883
+ aws_update_tag,
884
+ )
732
885
 
733
886
 
734
887
  @timeit
735
888
  def sync_roles(
736
- neo4j_session: neo4j.Session, boto3_session: boto3.session.Session, current_aws_account_id: str,
737
- aws_update_tag: int, common_job_parameters: Dict,
889
+ neo4j_session: neo4j.Session,
890
+ boto3_session: boto3.session.Session,
891
+ current_aws_account_id: str,
892
+ aws_update_tag: int,
893
+ common_job_parameters: Dict,
738
894
  ) -> None:
739
895
  logger.info("Syncing IAM roles for account '%s'.", current_aws_account_id)
740
896
  data = get_role_list_data(boto3_session)
741
- load_roles(neo4j_session, data['Roles'], current_aws_account_id, aws_update_tag)
897
+ load_roles(neo4j_session, data["Roles"], current_aws_account_id, aws_update_tag)
742
898
 
743
- sync_role_inline_policies(current_aws_account_id, boto3_session, data, neo4j_session, aws_update_tag)
899
+ sync_role_inline_policies(
900
+ current_aws_account_id,
901
+ boto3_session,
902
+ data,
903
+ neo4j_session,
904
+ aws_update_tag,
905
+ )
744
906
 
745
- sync_role_managed_policies(current_aws_account_id, boto3_session, data, neo4j_session, aws_update_tag)
907
+ sync_role_managed_policies(
908
+ current_aws_account_id,
909
+ boto3_session,
910
+ data,
911
+ neo4j_session,
912
+ aws_update_tag,
913
+ )
746
914
 
747
- run_cleanup_job('aws_import_roles_cleanup.json', neo4j_session, common_job_parameters)
915
+ run_cleanup_job(
916
+ "aws_import_roles_cleanup.json",
917
+ neo4j_session,
918
+ common_job_parameters,
919
+ )
748
920
 
749
921
 
750
922
  def sync_role_managed_policies(
751
- current_aws_account_id: str, boto3_session: boto3.session.Session, data: Dict,
752
- neo4j_session: neo4j.Session, aws_update_tag: int,
923
+ current_aws_account_id: str,
924
+ boto3_session: boto3.session.Session,
925
+ data: Dict,
926
+ neo4j_session: neo4j.Session,
927
+ aws_update_tag: int,
753
928
  ) -> None:
754
- logger.info("Syncing IAM role managed policies for account '%s'.", current_aws_account_id)
929
+ logger.info(
930
+ "Syncing IAM role managed policies for account '%s'.",
931
+ current_aws_account_id,
932
+ )
755
933
  managed_policy_data = get_role_managed_policy_data(boto3_session, data["Roles"])
756
934
  transform_policy_data(managed_policy_data, PolicyType.managed.value)
757
- load_policy_data(neo4j_session, managed_policy_data, PolicyType.managed.value, aws_update_tag)
935
+ load_policy_data(
936
+ neo4j_session,
937
+ managed_policy_data,
938
+ PolicyType.managed.value,
939
+ aws_update_tag,
940
+ )
758
941
 
759
942
 
760
943
  def sync_role_inline_policies(
761
- current_aws_account_id: str, boto3_session: boto3.session.Session, data: Dict,
762
- neo4j_session: neo4j.Session, aws_update_tag: int,
944
+ current_aws_account_id: str,
945
+ boto3_session: boto3.session.Session,
946
+ data: Dict,
947
+ neo4j_session: neo4j.Session,
948
+ aws_update_tag: int,
763
949
  ) -> None:
764
- logger.info("Syncing IAM role inline policies for account '%s'.", current_aws_account_id)
950
+ logger.info(
951
+ "Syncing IAM role inline policies for account '%s'.",
952
+ current_aws_account_id,
953
+ )
765
954
  inline_policy_data = get_role_policy_data(boto3_session, data["Roles"])
766
955
  transform_policy_data(inline_policy_data, PolicyType.inline.value)
767
- load_policy_data(neo4j_session, inline_policy_data, PolicyType.inline.value, aws_update_tag)
956
+ load_policy_data(
957
+ neo4j_session,
958
+ inline_policy_data,
959
+ PolicyType.inline.value,
960
+ aws_update_tag,
961
+ )
768
962
 
769
963
 
770
964
  @timeit
771
965
  def sync_group_memberships(
772
- neo4j_session: neo4j.Session, boto3_session: boto3.session.Session,
773
- current_aws_account_id: str, aws_update_tag: int, common_job_parameters: Dict,
966
+ neo4j_session: neo4j.Session,
967
+ boto3_session: boto3.session.Session,
968
+ current_aws_account_id: str,
969
+ aws_update_tag: int,
970
+ common_job_parameters: Dict,
774
971
  ) -> None:
775
- logger.info("Syncing IAM group membership for account '%s'.", current_aws_account_id)
776
- query = "MATCH (group:AWSGroup)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ACCOUNT_ID}) " \
777
- "return group.name as name, group.arn as arn;"
972
+ logger.info(
973
+ "Syncing IAM group membership for account '%s'.",
974
+ current_aws_account_id,
975
+ )
976
+ query = (
977
+ "MATCH (group:AWSGroup)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ACCOUNT_ID}) "
978
+ "return group.name as name, group.arn as arn;"
979
+ )
778
980
  groups = neo4j_session.run(query, AWS_ACCOUNT_ID=current_aws_account_id)
779
- groups_membership = {group["arn"]: get_group_membership_data(boto3_session, group["name"]) for group in groups}
981
+ groups_membership = {
982
+ group["arn"]: get_group_membership_data(boto3_session, group["name"])
983
+ for group in groups
984
+ }
780
985
  load_group_memberships(neo4j_session, groups_membership, aws_update_tag)
781
986
  run_cleanup_job(
782
- 'aws_import_groups_membership_cleanup.json',
987
+ "aws_import_groups_membership_cleanup.json",
783
988
  neo4j_session,
784
989
  common_job_parameters,
785
990
  )
@@ -787,19 +992,27 @@ def sync_group_memberships(
787
992
 
788
993
  @timeit
789
994
  def sync_user_access_keys(
790
- neo4j_session: neo4j.Session, boto3_session: boto3.session.Session,
791
- current_aws_account_id: str, aws_update_tag: int, common_job_parameters: Dict,
995
+ neo4j_session: neo4j.Session,
996
+ boto3_session: boto3.session.Session,
997
+ current_aws_account_id: str,
998
+ aws_update_tag: int,
999
+ common_job_parameters: Dict,
792
1000
  ) -> None:
793
- logger.info("Syncing IAM user access keys for account '%s'.", current_aws_account_id)
794
- query = "MATCH (user:AWSUser)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ACCOUNT_ID}) " \
795
- "RETURN user.name as name, user.arn as arn"
1001
+ logger.info(
1002
+ "Syncing IAM user access keys for account '%s'.",
1003
+ current_aws_account_id,
1004
+ )
1005
+ query = (
1006
+ "MATCH (user:AWSUser)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ACCOUNT_ID}) "
1007
+ "RETURN user.name as name, user.arn as arn"
1008
+ )
796
1009
  for user in neo4j_session.run(query, AWS_ACCOUNT_ID=current_aws_account_id):
797
1010
  access_keys = get_account_access_key_data(boto3_session, user["name"])
798
1011
  if access_keys:
799
1012
  account_access_keys = {user["arn"]: access_keys}
800
1013
  load_user_access_keys(neo4j_session, account_access_keys, aws_update_tag)
801
1014
  run_cleanup_job(
802
- 'aws_import_account_access_key_cleanup.json',
1015
+ "aws_import_account_access_key_cleanup.json",
803
1016
  neo4j_session,
804
1017
  common_job_parameters,
805
1018
  )
@@ -807,24 +1020,67 @@ def sync_user_access_keys(
807
1020
 
808
1021
  @timeit
809
1022
  def sync(
810
- neo4j_session: neo4j.Session, boto3_session: boto3.session.Session, regions: List[str], current_aws_account_id: str,
811
- update_tag: int, common_job_parameters: Dict,
1023
+ neo4j_session: neo4j.Session,
1024
+ boto3_session: boto3.session.Session,
1025
+ regions: List[str],
1026
+ current_aws_account_id: str,
1027
+ update_tag: int,
1028
+ common_job_parameters: Dict,
812
1029
  ) -> None:
813
1030
  logger.info("Syncing IAM for account '%s'.", current_aws_account_id)
814
1031
  # This module only syncs IAM information that is in use.
815
1032
  # As such only policies that are attached to a user, role or group are synced
816
- sync_users(neo4j_session, boto3_session, current_aws_account_id, update_tag, common_job_parameters)
817
- sync_groups(neo4j_session, boto3_session, current_aws_account_id, update_tag, common_job_parameters)
818
- sync_roles(neo4j_session, boto3_session, current_aws_account_id, update_tag, common_job_parameters)
819
- sync_group_memberships(neo4j_session, boto3_session, current_aws_account_id, update_tag, common_job_parameters)
820
- sync_assumerole_relationships(neo4j_session, current_aws_account_id, update_tag, common_job_parameters)
821
- sync_user_access_keys(neo4j_session, boto3_session, current_aws_account_id, update_tag, common_job_parameters)
822
- run_cleanup_job('aws_import_principals_cleanup.json', neo4j_session, common_job_parameters)
1033
+ sync_users(
1034
+ neo4j_session,
1035
+ boto3_session,
1036
+ current_aws_account_id,
1037
+ update_tag,
1038
+ common_job_parameters,
1039
+ )
1040
+ sync_groups(
1041
+ neo4j_session,
1042
+ boto3_session,
1043
+ current_aws_account_id,
1044
+ update_tag,
1045
+ common_job_parameters,
1046
+ )
1047
+ sync_roles(
1048
+ neo4j_session,
1049
+ boto3_session,
1050
+ current_aws_account_id,
1051
+ update_tag,
1052
+ common_job_parameters,
1053
+ )
1054
+ sync_group_memberships(
1055
+ neo4j_session,
1056
+ boto3_session,
1057
+ current_aws_account_id,
1058
+ update_tag,
1059
+ common_job_parameters,
1060
+ )
1061
+ sync_assumerole_relationships(
1062
+ neo4j_session,
1063
+ current_aws_account_id,
1064
+ update_tag,
1065
+ common_job_parameters,
1066
+ )
1067
+ sync_user_access_keys(
1068
+ neo4j_session,
1069
+ boto3_session,
1070
+ current_aws_account_id,
1071
+ update_tag,
1072
+ common_job_parameters,
1073
+ )
1074
+ run_cleanup_job(
1075
+ "aws_import_principals_cleanup.json",
1076
+ neo4j_session,
1077
+ common_job_parameters,
1078
+ )
823
1079
  merge_module_sync_metadata(
824
1080
  neo4j_session,
825
- group_type='AWSAccount',
1081
+ group_type="AWSAccount",
826
1082
  group_id=current_aws_account_id,
827
- synced_type='AWSPrincipal',
1083
+ synced_type="AWSPrincipal",
828
1084
  update_tag=update_tag,
829
1085
  stat_handler=stat_handler,
830
1086
  )