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
@@ -10,9 +10,10 @@ from typing import List
10
10
  import neo4j
11
11
  import oci
12
12
 
13
- from . import utils
14
13
  from cartography.util import run_cleanup_job
15
14
 
15
+ from . import utils
16
+
16
17
  logger = logging.getLogger(__name__)
17
18
 
18
19
 
@@ -25,8 +26,17 @@ def sync_compartments(
25
26
  ) -> None:
26
27
  logger.debug("Syncing IAM compartments for account '%s'.", current_tenancy_id)
27
28
  data = get_compartment_list_data(iam, current_tenancy_id)
28
- load_compartments(neo4j_session, data['Compartments'], current_tenancy_id, oci_update_tag)
29
- run_cleanup_job('oci_import_compartments_cleanup.json', neo4j_session, common_job_parameters)
29
+ load_compartments(
30
+ neo4j_session,
31
+ data["Compartments"],
32
+ current_tenancy_id,
33
+ oci_update_tag,
34
+ )
35
+ run_cleanup_job(
36
+ "oci_import_compartments_cleanup.json",
37
+ neo4j_session,
38
+ common_job_parameters,
39
+ )
30
40
 
31
41
 
32
42
  def get_compartment_list_data_recurse(
@@ -35,11 +45,17 @@ def get_compartment_list_data_recurse(
35
45
  compartment_id: str,
36
46
  ) -> None:
37
47
 
38
- response = oci.pagination.list_call_get_all_results(iam.list_compartments, compartment_id)
48
+ response = oci.pagination.list_call_get_all_results(
49
+ iam.list_compartments,
50
+ compartment_id,
51
+ )
39
52
  if not response.data:
40
53
  return
41
54
  compartment_list.update(
42
- {"Compartments": list(compartment_list["Compartments"]) + utils.oci_object_to_json(response.data)},
55
+ {
56
+ "Compartments": list(compartment_list["Compartments"])
57
+ + utils.oci_object_to_json(response.data),
58
+ },
43
59
  )
44
60
  for compartment in response.data:
45
61
  get_compartment_list_data_recurse(iam, compartment_list, compartment.id)
@@ -122,7 +138,9 @@ def load_users(
122
138
  CAN_USE_API_KEYS=user["capabilities"]["can-use-api-keys"],
123
139
  CAN_USE_AUTH_TOKENS=user["capabilities"]["can-use-auth-tokens"],
124
140
  CAN_USE_CONSOLE_PASSWORD=user["capabilities"]["can-use-console-password"],
125
- CAN_USE_CUSTOMER_SECRET_KEYS=user["capabilities"]["can-use-customer-secret-keys"],
141
+ CAN_USE_CUSTOMER_SECRET_KEYS=user["capabilities"][
142
+ "can-use-customer-secret-keys"
143
+ ],
126
144
  CAN_USE_SMTP_CREDENTIALS=user["capabilities"]["can-use-smtp-credentials"],
127
145
  COMPARTMENT_ID=user["compartment-id"],
128
146
  OCI_TENANCY_ID=current_oci_tenancy_id,
@@ -134,8 +152,11 @@ def get_user_list_data(
134
152
  iam: oci.identity.identity_client.IdentityClient,
135
153
  current_tenancy_id: str,
136
154
  ) -> Dict[str, List[Dict[str, Any]]]:
137
- response = oci.pagination.list_call_get_all_results(iam.list_users, current_tenancy_id)
138
- return {'Users': utils.oci_object_to_json(response.data)}
155
+ response = oci.pagination.list_call_get_all_results(
156
+ iam.list_users,
157
+ current_tenancy_id,
158
+ )
159
+ return {"Users": utils.oci_object_to_json(response.data)}
139
160
 
140
161
 
141
162
  def sync_users(
@@ -147,16 +168,23 @@ def sync_users(
147
168
  ) -> None:
148
169
  logger.debug("Syncing IAM users for account '%s'.", current_tenancy_id)
149
170
  data = get_user_list_data(iam, current_tenancy_id)
150
- load_users(neo4j_session, data['Users'], current_tenancy_id, oci_update_tag)
151
- run_cleanup_job('oci_import_users_cleanup.json', neo4j_session, common_job_parameters)
171
+ load_users(neo4j_session, data["Users"], current_tenancy_id, oci_update_tag)
172
+ run_cleanup_job(
173
+ "oci_import_users_cleanup.json",
174
+ neo4j_session,
175
+ common_job_parameters,
176
+ )
152
177
 
153
178
 
154
179
  def get_group_list_data(
155
180
  iam: oci.identity.identity_client.IdentityClient,
156
181
  current_tenancy_id: str,
157
182
  ) -> Dict[str, List[Dict[str, Any]]]:
158
- response = oci.pagination.list_call_get_all_results(iam.list_groups, current_tenancy_id)
159
- return {'Groups': utils.oci_object_to_json(response.data)}
183
+ response = oci.pagination.list_call_get_all_results(
184
+ iam.list_groups,
185
+ current_tenancy_id,
186
+ )
187
+ return {"Groups": utils.oci_object_to_json(response.data)}
160
188
 
161
189
 
162
190
  def load_groups(
@@ -200,7 +228,11 @@ def sync_groups(
200
228
  logger.debug("Syncing IAM groups for account '%s'.", current_tenancy_id)
201
229
  data = get_group_list_data(iam, current_tenancy_id)
202
230
  load_groups(neo4j_session, data["Groups"], current_tenancy_id, oci_update_tag)
203
- run_cleanup_job('oci_import_groups_cleanup.json', neo4j_session, common_job_parameters)
231
+ run_cleanup_job(
232
+ "oci_import_groups_cleanup.json",
233
+ neo4j_session,
234
+ common_job_parameters,
235
+ )
204
236
 
205
237
 
206
238
  def get_group_membership_data(
@@ -209,9 +241,11 @@ def get_group_membership_data(
209
241
  current_tenancy_id: str,
210
242
  ) -> Dict[str, List[Dict[str, Any]]]:
211
243
  response = oci.pagination.list_call_get_all_results(
212
- iam.list_user_group_memberships, compartment_id=current_tenancy_id, group_id=group_id,
244
+ iam.list_user_group_memberships,
245
+ compartment_id=current_tenancy_id,
246
+ group_id=group_id,
213
247
  )
214
- return {'GroupMemberships': utils.oci_object_to_json(response.data)}
248
+ return {"GroupMemberships": utils.oci_object_to_json(response.data)}
215
249
 
216
250
 
217
251
  def sync_group_memberships(
@@ -222,15 +256,18 @@ def sync_group_memberships(
222
256
  common_job_parameters: Dict[str, Any],
223
257
  ) -> None:
224
258
  logger.debug("Syncing IAM group membership for account '%s'.", current_tenancy_id)
225
- query = "MATCH (group:OCIGroup)<-[:RESOURCE]-(OCITenancy{ocid: $OCI_TENANCY_ID}) " \
226
- "return group.name as name, group.ocid as ocid;"
259
+ query = (
260
+ "MATCH (group:OCIGroup)<-[:RESOURCE]-(OCITenancy{ocid: $OCI_TENANCY_ID}) "
261
+ "return group.name as name, group.ocid as ocid;"
262
+ )
227
263
  groups = neo4j_session.run(query, OCI_TENANCY_ID=current_tenancy_id)
228
264
  groups_membership = {
229
- group["ocid"]: get_group_membership_data(iam, group['ocid'], current_tenancy_id) for group in groups
265
+ group["ocid"]: get_group_membership_data(iam, group["ocid"], current_tenancy_id)
266
+ for group in groups
230
267
  }
231
268
  load_group_memberships(neo4j_session, groups_membership, oci_update_tag)
232
269
  run_cleanup_job(
233
- 'oci_import_groups_membership_cleanup.json',
270
+ "oci_import_groups_membership_cleanup.json",
234
271
  neo4j_session,
235
272
  common_job_parameters,
236
273
  )
@@ -298,8 +335,11 @@ def get_policy_list_data(
298
335
  iam: oci.identity.identity_client.IdentityClient,
299
336
  current_tenancy_id: str,
300
337
  ) -> Dict[str, List[Dict[str, Any]]]:
301
- response = oci.pagination.list_call_get_all_results(iam.list_policies, compartment_id=current_tenancy_id)
302
- return {'Policies': utils.oci_object_to_json(response.data)}
338
+ response = oci.pagination.list_call_get_all_results(
339
+ iam.list_policies,
340
+ compartment_id=current_tenancy_id,
341
+ )
342
+ return {"Policies": utils.oci_object_to_json(response.data)}
303
343
 
304
344
 
305
345
  def sync_policies(
@@ -313,12 +353,23 @@ def sync_policies(
313
353
  compartments = utils.get_compartments_in_tenancy(neo4j_session, current_tenancy_id)
314
354
  for compartment in compartments:
315
355
  logger.debug(
316
- "Syncing OCI policies for compartment '%s' in account '%s'.", compartment['ocid'], current_tenancy_id,
356
+ "Syncing OCI policies for compartment '%s' in account '%s'.",
357
+ compartment["ocid"],
358
+ current_tenancy_id,
317
359
  )
318
360
  data = get_policy_list_data(iam, compartment["ocid"])
319
- if (data["Policies"]):
320
- load_policies(neo4j_session, data["Policies"], current_tenancy_id, oci_update_tag)
321
- run_cleanup_job('oci_import_policies_cleanup.json', neo4j_session, common_job_parameters)
361
+ if data["Policies"]:
362
+ load_policies(
363
+ neo4j_session,
364
+ data["Policies"],
365
+ current_tenancy_id,
366
+ oci_update_tag,
367
+ )
368
+ run_cleanup_job(
369
+ "oci_import_policies_cleanup.json",
370
+ neo4j_session,
371
+ common_job_parameters,
372
+ )
322
373
 
323
374
 
324
375
  def load_oci_policy_group_reference(
@@ -378,22 +429,33 @@ def sync_oci_policy_references(
378
429
  for policy in policies:
379
430
  check_compart = policy["compartmentid"]
380
431
  for statement in policy["statements"]:
381
- m = re.search('(?<=group\\s)[^ ]*(?=\\s)', statement)
432
+ m = re.search("(?<=group\\s)[^ ]*(?=\\s)", statement)
382
433
  if m:
383
434
  for group in groups:
384
435
  if group["name"].lower() == m.group(0).lower():
385
436
  load_oci_policy_group_reference(
386
- neo4j_session, policy["ocid"], group["ocid"], tenancy_id, oci_update_tag,
437
+ neo4j_session,
438
+ policy["ocid"],
439
+ group["ocid"],
440
+ tenancy_id,
441
+ oci_update_tag,
387
442
  )
388
- m = re.search('(?<=compartment\\s)[^ ]*(?=$)', statement)
443
+ m = re.search("(?<=compartment\\s)[^ ]*(?=$)", statement)
389
444
  if m:
390
445
  for compartment in compartments:
391
446
  # Only look at the compartment or subcompartment name referenced in the policy statement
392
447
  # in which the policy is a member of.
393
- if compartment["ocid"] == check_compart or compartment["compartmentid"] == check_compart:
448
+ if (
449
+ compartment["ocid"] == check_compart
450
+ or compartment["compartmentid"] == check_compart
451
+ ):
394
452
  if compartment["name"].lower() == m.group(0).lower():
395
453
  load_oci_policy_compartment_reference(
396
- neo4j_session, policy["ocid"], compartment['ocid'], tenancy_id, oci_update_tag,
454
+ neo4j_session,
455
+ policy["ocid"],
456
+ compartment["ocid"],
457
+ tenancy_id,
458
+ oci_update_tag,
397
459
  )
398
460
 
399
461
 
@@ -401,8 +463,11 @@ def get_region_subscriptions_list_data(
401
463
  iam: oci.identity.identity_client.IdentityClient,
402
464
  current_tenancy_id: str,
403
465
  ) -> Dict[str, List[Dict[str, Any]]]:
404
- response = oci.pagination.list_call_get_all_results(iam.list_region_subscriptions, current_tenancy_id)
405
- return {'RegionSubscriptions': utils.oci_object_to_json(response.data)}
466
+ response = oci.pagination.list_call_get_all_results(
467
+ iam.list_region_subscriptions,
468
+ current_tenancy_id,
469
+ )
470
+ return {"RegionSubscriptions": utils.oci_object_to_json(response.data)}
406
471
 
407
472
 
408
473
  def load_region_subscriptions(
@@ -438,9 +503,17 @@ def sync_region_subscriptions(
438
503
  oci_update_tag: int,
439
504
  common_job_parameters: Dict[str, Any],
440
505
  ) -> None:
441
- logger.debug("Syncing IAM region subscriptions for account '%s'.", current_tenancy_id)
506
+ logger.debug(
507
+ "Syncing IAM region subscriptions for account '%s'.",
508
+ current_tenancy_id,
509
+ )
442
510
  data = get_region_subscriptions_list_data(iam, current_tenancy_id)
443
- load_region_subscriptions(neo4j_session, data["RegionSubscriptions"], current_tenancy_id, oci_update_tag)
511
+ load_region_subscriptions(
512
+ neo4j_session,
513
+ data["RegionSubscriptions"],
514
+ current_tenancy_id,
515
+ oci_update_tag,
516
+ )
444
517
  # run_cleanup_job('oci_import_region_subscriptions_cleanup.json', neo4j_session, common_job_parameters)
445
518
 
446
519
 
@@ -454,8 +527,31 @@ def sync(
454
527
  logger.info("Syncing IAM for account '%s'.", tenancy_id)
455
528
  sync_users(neo4j_session, iam, tenancy_id, oci_update_tag, common_job_parameters)
456
529
  sync_groups(neo4j_session, iam, tenancy_id, oci_update_tag, common_job_parameters)
457
- sync_group_memberships(neo4j_session, iam, tenancy_id, oci_update_tag, common_job_parameters)
458
- sync_compartments(neo4j_session, iam, tenancy_id, oci_update_tag, common_job_parameters)
530
+ sync_group_memberships(
531
+ neo4j_session,
532
+ iam,
533
+ tenancy_id,
534
+ oci_update_tag,
535
+ common_job_parameters,
536
+ )
537
+ sync_compartments(
538
+ neo4j_session,
539
+ iam,
540
+ tenancy_id,
541
+ oci_update_tag,
542
+ common_job_parameters,
543
+ )
459
544
  sync_policies(neo4j_session, iam, tenancy_id, oci_update_tag, common_job_parameters)
460
- sync_oci_policy_references(neo4j_session, tenancy_id, oci_update_tag, common_job_parameters)
461
- sync_region_subscriptions(neo4j_session, iam, tenancy_id, oci_update_tag, common_job_parameters)
545
+ sync_oci_policy_references(
546
+ neo4j_session,
547
+ tenancy_id,
548
+ oci_update_tag,
549
+ common_job_parameters,
550
+ )
551
+ sync_region_subscriptions(
552
+ neo4j_session,
553
+ iam,
554
+ tenancy_id,
555
+ oci_update_tag,
556
+ common_job_parameters,
557
+ )
@@ -41,7 +41,7 @@ def get_oci_account_default() -> Dict[str, Any]:
41
41
  def get_oci_profile_names_from_config() -> List[Any]:
42
42
  config_path = oci.config._get_config_path_with_fallback("~/.oci/config")
43
43
  config = open(config_path).read()
44
- pattern = r'\[(.*)\]'
44
+ pattern = r"\[(.*)\]"
45
45
  m = re.findall(pattern, config)
46
46
  return m
47
47
 
@@ -52,16 +52,20 @@ def get_oci_accounts_from_config() -> Dict[str, Any]:
52
52
 
53
53
  d = {}
54
54
  for profile_name in available_profiles:
55
- if profile_name == 'DEFAULT':
55
+ if profile_name == "DEFAULT":
56
56
  logger.debug("Skipping OCI profile 'DEFAULT'.")
57
57
  continue
58
58
  try:
59
- profile_oci_credentials = oci.config.from_file("~/.oci/config", profile_name)
59
+ profile_oci_credentials = oci.config.from_file(
60
+ "~/.oci/config",
61
+ profile_name,
62
+ )
60
63
  oci.config.validate_config(profile_oci_credentials)
61
64
  except (ConfigFileNotFound, ProfileNotFound, InvalidConfig) as e:
62
65
  logger.debug(
63
66
  "Error occurred calling oci.config.from_file with profile_name '%s'.",
64
- profile_name, exc_info=True,
67
+ profile_name,
68
+ exc_info=True,
65
69
  )
66
70
  logger.error(
67
71
  (
@@ -104,8 +108,11 @@ def load_oci_accounts(
104
108
  )
105
109
 
106
110
 
107
- def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any]) -> None:
108
- run_cleanup_job('oci_tenancy_cleanup.json', neo4j_session, common_job_parameters)
111
+ def cleanup(
112
+ neo4j_session: neo4j.Session,
113
+ common_job_parameters: Dict[str, Any],
114
+ ) -> None:
115
+ run_cleanup_job("oci_tenancy_cleanup.json", neo4j_session, common_job_parameters)
109
116
 
110
117
 
111
118
  def sync(
@@ -22,47 +22,70 @@ def replace_char_in_dict(in_dict: Dict[str, Any]) -> Dict[str, Any]:
22
22
  for dict_key, dict_val in in_dict.items():
23
23
  if isinstance(dict_val, dict):
24
24
  dict_val = replace_char_in_dict(dict_val)
25
- out_dict[dict_key.replace('_', '-')] = dict_val
25
+ out_dict[dict_key.replace("_", "-")] = dict_val
26
26
  return out_dict
27
27
 
28
28
 
29
29
  # Grab list of all compartments and sub-compartments in neo4j already populated by iam.
30
- def get_compartments_in_tenancy(neo4j_session: neo4j.Session, tenancy_id: str) -> neo4j.Result:
31
- query = "MATCH (OCITenancy{ocid: $OCI_TENANCY_ID})-[*]->(compartment:OCICompartment) " \
32
- "return DISTINCT compartment.name as name, compartment.ocid as ocid, " \
33
- "compartment.compartmentid as compartmentid;"
30
+ def get_compartments_in_tenancy(
31
+ neo4j_session: neo4j.Session,
32
+ tenancy_id: str,
33
+ ) -> neo4j.Result:
34
+ query = (
35
+ "MATCH (OCITenancy{ocid: $OCI_TENANCY_ID})-[*]->(compartment:OCICompartment) "
36
+ "return DISTINCT compartment.name as name, compartment.ocid as ocid, "
37
+ "compartment.compartmentid as compartmentid;"
38
+ )
34
39
  return neo4j_session.run(query, OCI_TENANCY_ID=tenancy_id)
35
40
 
36
41
 
37
42
  # Grab list of all groups in neo4j already populated by iam.
38
- def get_groups_in_tenancy(neo4j_session: neo4j.Session, tenancy_id: str) -> neo4j.Result:
39
- query = "MATCH (OCITenancy{ocid: $OCI_TENANCY_ID})-[*]->(group:OCIGroup)" \
40
- "return DISTINCT group.name as name, group.ocid as ocid;"
43
+ def get_groups_in_tenancy(
44
+ neo4j_session: neo4j.Session,
45
+ tenancy_id: str,
46
+ ) -> neo4j.Result:
47
+ query = (
48
+ "MATCH (OCITenancy{ocid: $OCI_TENANCY_ID})-[*]->(group:OCIGroup)"
49
+ "return DISTINCT group.name as name, group.ocid as ocid;"
50
+ )
41
51
  return neo4j_session.run(query, OCI_TENANCY_ID=tenancy_id)
42
52
 
43
53
 
44
54
  # Grab list of all policies in neo4j already populated by iam.
45
- def get_policies_in_tenancy(neo4j_session: neo4j.Session, tenancy_id: str) -> neo4j.Result:
46
- query = "MATCH (OCITenancy{ocid: $OCI_TENANCY_ID})-[*]->(policy:OCIPolicy)" \
47
- "return DISTINCT policy.name as name, policy.ocid as ocid, policy.statements as statements, " \
48
- "policy.compartmentid as compartmentid;"
55
+ def get_policies_in_tenancy(
56
+ neo4j_session: neo4j.Session,
57
+ tenancy_id: str,
58
+ ) -> neo4j.Result:
59
+ query = (
60
+ "MATCH (OCITenancy{ocid: $OCI_TENANCY_ID})-[*]->(policy:OCIPolicy)"
61
+ "return DISTINCT policy.name as name, policy.ocid as ocid, policy.statements as statements, "
62
+ "policy.compartmentid as compartmentid;"
63
+ )
49
64
  return neo4j_session.run(query, OCI_TENANCY_ID=tenancy_id)
50
65
 
51
66
 
52
67
  # Grab list of all regions in neo4j already populated by iam.
53
- def get_regions_in_tenancy(neo4j_session: neo4j.Session, tenancy_id: str) -> neo4j.Result:
54
- query = "MATCH (OCITenancy{ocid: $OCI_TENANCY_ID})-->(region:OCIRegion)" \
55
- "return DISTINCT region.name as name, region.key as key;"
68
+ def get_regions_in_tenancy(
69
+ neo4j_session: neo4j.Session,
70
+ tenancy_id: str,
71
+ ) -> neo4j.Result:
72
+ query = (
73
+ "MATCH (OCITenancy{ocid: $OCI_TENANCY_ID})-->(region:OCIRegion)"
74
+ "return DISTINCT region.name as name, region.key as key;"
75
+ )
56
76
  return neo4j_session.run(query, OCI_TENANCY_ID=tenancy_id)
57
77
 
58
78
 
59
79
  # Grab list of all security groups in neo4j already populated by network. Need to handle regions for this one.
60
80
  def get_security_groups_in_tenancy(
61
81
  neo4j_session: neo4j.Session,
62
- tenancy_id: str, region: str,
82
+ tenancy_id: str,
83
+ region: str,
63
84
  ) -> neo4j.Result:
64
- query = "MATCH (OCITenancy{ocid: $OCI_TENANCY_ID})-[*]->(security_group:OCINetworkSecurityGroup)-[OCI_REGION]->" \
65
- "(region:OCIRegion{name: $OCI_REGION})" \
66
- "return DISTINCT security_group.name as name, security_group.ocid as ocid, security_group.compartmentid " \
67
- "as compartmentid;"
85
+ query = (
86
+ "MATCH (OCITenancy{ocid: $OCI_TENANCY_ID})-[*]->(security_group:OCINetworkSecurityGroup)-[OCI_REGION]->"
87
+ "(region:OCIRegion{name: $OCI_REGION})"
88
+ "return DISTINCT security_group.name as name, security_group.ocid as ocid, security_group.compartmentid "
89
+ "as compartmentid;"
90
+ )
68
91
  return neo4j_session.run(query, OCI_TENANCY_ID=tenancy_id, OCI_REGION=region)
@@ -24,19 +24,25 @@ stat_handler = get_stats_client(__name__)
24
24
 
25
25
 
26
26
  @timeit
27
- def _cleanup_okta_organizations(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
27
+ def _cleanup_okta_organizations(
28
+ neo4j_session: neo4j.Session,
29
+ common_job_parameters: Dict,
30
+ ) -> None:
28
31
  """
29
32
  Remove stale Okta organization
30
33
  :param neo4j_session: The Neo4j session
31
34
  :param common_job_parameters: Parameters to carry to the cleanup job
32
35
  :return: Nothing
33
36
  """
34
- run_cleanup_job('okta_import_cleanup.json', neo4j_session, common_job_parameters)
37
+ run_cleanup_job("okta_import_cleanup.json", neo4j_session, common_job_parameters)
35
38
  cleanup_okta_groups(neo4j_session, common_job_parameters)
36
39
 
37
40
 
38
- def cleanup_okta_groups(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
39
- run_cleanup_job('okta_groups_cleanup.json', neo4j_session, common_job_parameters)
41
+ def cleanup_okta_groups(
42
+ neo4j_session: neo4j.Session,
43
+ common_job_parameters: Dict,
44
+ ) -> None:
45
+ run_cleanup_job("okta_groups_cleanup.json", neo4j_session, common_job_parameters)
40
46
 
41
47
 
42
48
  @timeit
@@ -62,34 +68,79 @@ def start_okta_ingestion(neo4j_session: neo4j.Session, config: Config) -> None:
62
68
 
63
69
  state = OktaSyncState()
64
70
 
65
- organization.create_okta_organization(neo4j_session, config.okta_org_id, config.update_tag)
66
- users.sync_okta_users(neo4j_session, config.okta_org_id, config.update_tag, config.okta_api_key, state)
67
- groups.sync_okta_groups(neo4j_session, config.okta_org_id, config.update_tag, config.okta_api_key, state)
68
- applications.sync_okta_applications(neo4j_session, config.okta_org_id, config.update_tag, config.okta_api_key)
69
- factors.sync_users_factors(neo4j_session, config.okta_org_id, config.update_tag, config.okta_api_key, state)
70
- origins.sync_trusted_origins(neo4j_session, config.okta_org_id, config.update_tag, config.okta_api_key)
71
- awssaml.sync_okta_aws_saml(neo4j_session, config.okta_saml_role_regex, config.update_tag, config.okta_org_id)
71
+ organization.create_okta_organization(
72
+ neo4j_session,
73
+ config.okta_org_id,
74
+ config.update_tag,
75
+ )
76
+ users.sync_okta_users(
77
+ neo4j_session,
78
+ config.okta_org_id,
79
+ config.update_tag,
80
+ config.okta_api_key,
81
+ state,
82
+ )
83
+ groups.sync_okta_groups(
84
+ neo4j_session,
85
+ config.okta_org_id,
86
+ config.update_tag,
87
+ config.okta_api_key,
88
+ state,
89
+ )
90
+ applications.sync_okta_applications(
91
+ neo4j_session,
92
+ config.okta_org_id,
93
+ config.update_tag,
94
+ config.okta_api_key,
95
+ )
96
+ factors.sync_users_factors(
97
+ neo4j_session,
98
+ config.okta_org_id,
99
+ config.update_tag,
100
+ config.okta_api_key,
101
+ state,
102
+ )
103
+ origins.sync_trusted_origins(
104
+ neo4j_session,
105
+ config.okta_org_id,
106
+ config.update_tag,
107
+ config.okta_api_key,
108
+ )
109
+ awssaml.sync_okta_aws_saml(
110
+ neo4j_session,
111
+ config.okta_saml_role_regex,
112
+ config.update_tag,
113
+ config.okta_org_id,
114
+ )
72
115
 
73
116
  # need creds with permission
74
117
  # soft fail as some won't be able to get such high priv token
75
118
  # when we get the E0000006 error
76
119
  # see https://developer.okta.com/docs/reference/error-codes/
77
120
  try:
78
- roles.sync_roles(neo4j_session, config.okta_org_id, config.update_tag, config.okta_api_key, state)
121
+ roles.sync_roles(
122
+ neo4j_session,
123
+ config.okta_org_id,
124
+ config.update_tag,
125
+ config.okta_api_key,
126
+ state,
127
+ )
79
128
  except OktaError as okta_error:
80
129
  logger.warning(f"Unable to pull admin roles got {okta_error}")
81
130
 
82
131
  # Getting roles requires super admin which most won't be able to get easily
83
132
  if okta_error.error_code == "E0000006":
84
- logger.warning("Unable to sync admin roles - api token needs admin rights to pull admin roles data")
133
+ logger.warning(
134
+ "Unable to sync admin roles - api token needs admin rights to pull admin roles data",
135
+ )
85
136
 
86
137
  _cleanup_okta_organizations(neo4j_session, common_job_parameters)
87
138
 
88
139
  merge_module_sync_metadata(
89
140
  neo4j_session,
90
- group_type='OktaOrganization',
141
+ group_type="OktaOrganization",
91
142
  group_id=config.okta_org_id,
92
- synced_type='OktaOrganization',
143
+ synced_type="OktaOrganization",
93
144
  update_tag=config.update_tag,
94
145
  stat_handler=stat_handler,
95
146
  )