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
@@ -0,0 +1,112 @@
1
+ # cartography/intel/entra/ou.py
2
+ import logging
3
+ from typing import Any
4
+
5
+ import neo4j
6
+ from azure.identity import ClientSecretCredential
7
+ from msgraph import GraphServiceClient
8
+ from msgraph.generated.models.administrative_unit import AdministrativeUnit
9
+
10
+ from cartography.client.core.tx import load
11
+ from cartography.graph.job import GraphJob
12
+ from cartography.intel.entra.users import load_tenant
13
+ from cartography.models.entra.ou import EntraOUSchema
14
+ from cartography.util import timeit
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ @timeit
20
+ async def get_entra_ous(client: GraphServiceClient) -> list[AdministrativeUnit]:
21
+ """
22
+ Get all OUs from Microsoft Graph API with pagination support
23
+ """
24
+ all_units: list[AdministrativeUnit] = []
25
+ request = client.directory.administrative_units.request()
26
+
27
+ while request:
28
+ response = await request.get()
29
+ all_units.extend(response.value)
30
+ request = response.odata_next_link if response.odata_next_link else None
31
+
32
+ return all_units
33
+
34
+
35
+ def transform_ous(
36
+ units: list[AdministrativeUnit], tenant_id: str
37
+ ) -> list[dict[str, Any]]:
38
+ """
39
+ Transform the API response into the format expected by our schema
40
+ """
41
+ result: list[dict[str, Any]] = []
42
+ for unit in units:
43
+ transformed_unit = {
44
+ "id": unit.id,
45
+ "display_name": unit.display_name,
46
+ "description": unit.description,
47
+ "visibility": unit.visibility,
48
+ "membership_type": unit.membership_type,
49
+ "is_member_management_restricted": unit.is_member_management_restricted,
50
+ "deleted_date_time": unit.deleted_date_time,
51
+ "tenant_id": tenant_id,
52
+ }
53
+ result.append(transformed_unit)
54
+ return result
55
+
56
+
57
+ @timeit
58
+ def load_ous(
59
+ neo4j_session: neo4j.Session,
60
+ units: list[dict[str, Any]],
61
+ update_tag: int,
62
+ common_job_parameters: dict[str, Any],
63
+ ) -> None:
64
+ logger.info(f"Loading {len(units)} Entra OUs")
65
+ load(
66
+ neo4j_session,
67
+ EntraOUSchema(),
68
+ units,
69
+ lastupdated=update_tag,
70
+ TENANT_ID=common_job_parameters["TENANT_ID"],
71
+ UPDATE_TAG=common_job_parameters["UPDATE_TAG"],
72
+ )
73
+
74
+
75
+ def cleanup_ous(
76
+ neo4j_session: neo4j.Session, common_job_parameters: dict[str, Any]
77
+ ) -> None:
78
+ GraphJob.from_node_schema(EntraOUSchema(), common_job_parameters).run(neo4j_session)
79
+
80
+
81
+ @timeit
82
+ async def sync_entra_ous(
83
+ neo4j_session: neo4j.Session,
84
+ tenant_id: str,
85
+ client_id: str,
86
+ client_secret: str,
87
+ update_tag: int,
88
+ common_job_parameters: dict[str, Any],
89
+ ) -> None:
90
+ """
91
+ Sync Entra OUs
92
+ """
93
+ # Initialize Graph client
94
+ credential = ClientSecretCredential(
95
+ tenant_id=tenant_id,
96
+ client_id=client_id,
97
+ client_secret=client_secret,
98
+ )
99
+ client = GraphServiceClient(
100
+ credential, scopes=["https://graph.microsoft.com/.default"]
101
+ )
102
+
103
+ # Get OUs
104
+ units = await get_entra_ous(client)
105
+ transformed_units = transform_ous(units, tenant_id)
106
+
107
+ # Load data
108
+ load_tenant(neo4j_session, {"id": tenant_id}, update_tag)
109
+ load_ous(neo4j_session, transformed_units, update_tag, common_job_parameters)
110
+
111
+ # Cleanup stale data
112
+ cleanup_ous(neo4j_session, common_job_parameters)
@@ -56,51 +56,51 @@ def transform_users(users: list[User]) -> list[dict[str, Any]]:
56
56
  result: list[dict[str, Any]] = []
57
57
  for user in users:
58
58
  transformed_user = {
59
- 'id': user.id,
60
- 'user_principal_name': user.user_principal_name,
61
- 'display_name': user.display_name,
62
- 'given_name': user.given_name,
63
- 'surname': user.surname,
64
- 'mail': user.mail,
65
- 'other_mails': user.other_mails,
66
- 'preferred_language': user.preferred_language,
67
- 'preferred_name': user.preferred_name,
68
- 'state': user.state,
69
- 'usage_location': user.usage_location,
70
- 'user_type': user.user_type,
71
- 'show_in_address_list': user.show_in_address_list,
72
- 'sign_in_sessions_valid_from_date_time': user.sign_in_sessions_valid_from_date_time,
73
- 'security_identifier': user.on_premises_security_identifier,
74
- 'account_enabled': user.account_enabled,
75
- 'age_group': user.age_group,
76
- 'business_phones': user.business_phones,
77
- 'city': user.city,
78
- 'company_name': user.company_name,
79
- 'consent_provided_for_minor': user.consent_provided_for_minor,
80
- 'country': user.country,
81
- 'created_date_time': user.created_date_time,
82
- 'creation_type': user.creation_type,
83
- 'deleted_date_time': user.deleted_date_time,
84
- 'department': user.department,
85
- 'employee_id': user.employee_id,
86
- 'employee_type': user.employee_type,
87
- 'external_user_state': user.external_user_state,
88
- 'external_user_state_change_date_time': user.external_user_state_change_date_time,
89
- 'hire_date': user.hire_date,
90
- 'is_management_restricted': user.is_management_restricted,
91
- 'is_resource_account': user.is_resource_account,
92
- 'job_title': user.job_title,
93
- 'last_password_change_date_time': user.last_password_change_date_time,
94
- 'mail_nickname': user.mail_nickname,
95
- 'office_location': user.office_location,
96
- 'on_premises_distinguished_name': user.on_premises_distinguished_name,
97
- 'on_premises_domain_name': user.on_premises_domain_name,
98
- 'on_premises_immutable_id': user.on_premises_immutable_id,
99
- 'on_premises_last_sync_date_time': user.on_premises_last_sync_date_time,
100
- 'on_premises_sam_account_name': user.on_premises_sam_account_name,
101
- 'on_premises_security_identifier': user.on_premises_security_identifier,
102
- 'on_premises_sync_enabled': user.on_premises_sync_enabled,
103
- 'on_premises_user_principal_name': user.on_premises_user_principal_name,
59
+ "id": user.id,
60
+ "user_principal_name": user.user_principal_name,
61
+ "display_name": user.display_name,
62
+ "given_name": user.given_name,
63
+ "surname": user.surname,
64
+ "mail": user.mail,
65
+ "other_mails": user.other_mails,
66
+ "preferred_language": user.preferred_language,
67
+ "preferred_name": user.preferred_name,
68
+ "state": user.state,
69
+ "usage_location": user.usage_location,
70
+ "user_type": user.user_type,
71
+ "show_in_address_list": user.show_in_address_list,
72
+ "sign_in_sessions_valid_from_date_time": user.sign_in_sessions_valid_from_date_time,
73
+ "security_identifier": user.on_premises_security_identifier,
74
+ "account_enabled": user.account_enabled,
75
+ "age_group": user.age_group,
76
+ "business_phones": user.business_phones,
77
+ "city": user.city,
78
+ "company_name": user.company_name,
79
+ "consent_provided_for_minor": user.consent_provided_for_minor,
80
+ "country": user.country,
81
+ "created_date_time": user.created_date_time,
82
+ "creation_type": user.creation_type,
83
+ "deleted_date_time": user.deleted_date_time,
84
+ "department": user.department,
85
+ "employee_id": user.employee_id,
86
+ "employee_type": user.employee_type,
87
+ "external_user_state": user.external_user_state,
88
+ "external_user_state_change_date_time": user.external_user_state_change_date_time,
89
+ "hire_date": user.hire_date,
90
+ "is_management_restricted": user.is_management_restricted,
91
+ "is_resource_account": user.is_resource_account,
92
+ "job_title": user.job_title,
93
+ "last_password_change_date_time": user.last_password_change_date_time,
94
+ "mail_nickname": user.mail_nickname,
95
+ "office_location": user.office_location,
96
+ "on_premises_distinguished_name": user.on_premises_distinguished_name,
97
+ "on_premises_domain_name": user.on_premises_domain_name,
98
+ "on_premises_immutable_id": user.on_premises_immutable_id,
99
+ "on_premises_last_sync_date_time": user.on_premises_last_sync_date_time,
100
+ "on_premises_sam_account_name": user.on_premises_sam_account_name,
101
+ "on_premises_security_identifier": user.on_premises_security_identifier,
102
+ "on_premises_sync_enabled": user.on_premises_sync_enabled,
103
+ "on_premises_user_principal_name": user.on_premises_user_principal_name,
104
104
  }
105
105
  result.append(transformed_user)
106
106
  return result
@@ -112,21 +112,21 @@ def transform_tenant(tenant: Organization, tenant_id: str) -> dict[str, Any]:
112
112
  Transform the tenant data into the format expected by our schema
113
113
  """
114
114
  return {
115
- 'id': tenant_id,
116
- 'created_date_time': tenant.created_date_time,
117
- 'default_usage_location': tenant.default_usage_location,
118
- 'deleted_date_time': tenant.deleted_date_time,
119
- 'display_name': tenant.display_name,
120
- 'marketing_notification_emails': tenant.marketing_notification_emails,
121
- 'mobile_device_management_authority': tenant.mobile_device_management_authority,
122
- 'on_premises_last_sync_date_time': tenant.on_premises_last_sync_date_time,
123
- 'on_premises_sync_enabled': tenant.on_premises_sync_enabled,
124
- 'partner_tenant_type': tenant.partner_tenant_type,
125
- 'postal_code': tenant.postal_code,
126
- 'preferred_language': tenant.preferred_language,
127
- 'state': tenant.state,
128
- 'street': tenant.street,
129
- 'tenant_type': tenant.tenant_type,
115
+ "id": tenant_id,
116
+ "created_date_time": tenant.created_date_time,
117
+ "default_usage_location": tenant.default_usage_location,
118
+ "deleted_date_time": tenant.deleted_date_time,
119
+ "display_name": tenant.display_name,
120
+ "marketing_notification_emails": tenant.marketing_notification_emails,
121
+ "mobile_device_management_authority": tenant.mobile_device_management_authority,
122
+ "on_premises_last_sync_date_time": tenant.on_premises_last_sync_date_time,
123
+ "on_premises_sync_enabled": tenant.on_premises_sync_enabled,
124
+ "partner_tenant_type": tenant.partner_tenant_type,
125
+ "postal_code": tenant.postal_code,
126
+ "preferred_language": tenant.preferred_language,
127
+ "state": tenant.state,
128
+ "street": tenant.street,
129
+ "tenant_type": tenant.tenant_type,
130
130
  }
131
131
 
132
132
 
@@ -161,8 +161,12 @@ def load_users(
161
161
  )
162
162
 
163
163
 
164
- def cleanup(neo4j_session: neo4j.Session, common_job_parameters: dict[str, Any]) -> None:
165
- GraphJob.from_node_schema(EntraUserSchema(), common_job_parameters).run(neo4j_session)
164
+ def cleanup(
165
+ neo4j_session: neo4j.Session, common_job_parameters: dict[str, Any]
166
+ ) -> None:
167
+ GraphJob.from_node_schema(EntraUserSchema(), common_job_parameters).run(
168
+ neo4j_session
169
+ )
166
170
 
167
171
 
168
172
  @timeit
@@ -190,7 +194,9 @@ async def sync_entra_users(
190
194
  client_id=client_id,
191
195
  client_secret=client_secret,
192
196
  )
193
- client = GraphServiceClient(credential, scopes=['https://graph.microsoft.com/.default'])
197
+ client = GraphServiceClient(
198
+ credential, scopes=["https://graph.microsoft.com/.default"]
199
+ )
194
200
 
195
201
  # Get tenant information
196
202
  tenant = await get_tenant(client)