Automating User Deprovisioning in Microsoft 365: OneDrive and Mailbox Reassignment
When an employee leaves an organization, it's critical to deprovision their accounts securely and efficiently, while ensuring business continuity. This article demonstrates a Python-based approach to automate user deprovisioning in Microsoft 365, focusing on:
- Disabling accounts in Active Directory (AD/ADDS)
- Disabling accounts in Entra ID (Azure AD)
- Assigning the user's OneDrive and mailbox access to their manager
We will walk through the following functions:
- terminate_employees_adds
- terminate_employees_entra
- grant_access_to_users_mailbox
Prerequisites
- Python 3.8+
- Required libraries:
requests
msal
(Microsoft Authentication Library)subprocess
(standard library)PnP.PowerShell
andExchangeOnlineManagement
PowerShell modules installed on a system with PowerShell Core- Service principal with appropriate permissions in Microsoft 365
- Certificate-based authentication for automation
1. Disabling Users in Active Directory (AD/ADDS)
The function terminate_employees_adds
connects to AD and disables user accounts. This is typically done using the ldap3
library, but the code can be adapted for other libraries or direct PowerShell calls.
def terminate_employees_adds(terminated_employees):
try:
conn = get_adds_Connection()
if not conn:
return
for employee in terminated_employees:
# Example: Disable the user account
user_dn = employee['distinguishedName']
conn.modify(user_dn, {'userAccountControl': [(ldap3.MODIFY_REPLACE, [514])]})
except Exception as e:
handle_global_exception(sys._getframe().f_code.co_name, e)
finally:
if conn:
conn.unbind()
- Explanation:
- Connects to AD using a service account.
- Iterates through the list of terminated employees.
- Sets the
userAccountControl
attribute to514
(disabled).
2. Disabling Users in Entra ID (Azure AD)
The function terminate_employees_entra
disables the user in Entra ID and then delegates OneDrive and mailbox access to the user's manager.
def terminate_employees_entra(terminated_employees, existing_employees):
try:
existing_employee_dict = {str(employee['hr_PositionID']).lower(): employee for employee in existing_employees}
for terminated_employee in terminated_employees:
terminated_user_reportsto_id = terminated_employee['hr_ReportsToPositionID']
if str(terminated_user_reportsto_id).lower() in existing_employee_dict:
manager = existing_employee_dict[str(terminated_user_reportsto_id).lower()]
manager_email = manager['entra_mail']
entra_id = terminated_employee.get('entra_id')
terminated_user_email = terminated_employee.get('entra_userPrincipalName')
if entra_id:
entra_onedrive_url = grant_access_to_users_onedrive(
terminated_user_email,
manager_email)
grant_access_to_users_mailbox(
terminated_user_email,
manager_email)
terminated_employee['entra_onedrive_url'] = entra_onedrive_url
except Exception as e:
handle_global_exception(sys._getframe().f_code.co_name, e)
return False
- Explanation:
- Looks up the manager for each terminated employee.
- Calls helper functions to delegate OneDrive and mailbox access to the manager.
3. Assigning OneDrive Access to the Manager
The function grant_access_to_users_onedrive
uses Microsoft Graph API to get the user's OneDrive URL, then uses PowerShell to assign the manager as the site owner.
def grant_access_to_users_onedrive(terminated_user_email, manager_email):
try:
access_token = get_access_token_API_Access_AAD()
url = f"https://graph.microsoft.com/v1.0/users/{terminated_user_email}/drive"
response = requests.get(url, headers={'Authorization': f'Bearer {access_token}'})
response.raise_for_status()
graph_data = response.json()
user_onedrive_url = graph_data['webUrl']
command_to_run = f'''
Import-Module PnP.PowerShell
Connect-PnPOnline -Url <SharePointRootUrl> -ClientId <AppId> -Tenant <TenantName> -CertificatePath <CertPath>
$OneDriveSiteUrl = "{user_onedrive_url.replace('/Documents', '')}"
$SiteCollAdmin = "{manager_email}"
Set-PnPTenantSite -Url $OneDriveSiteUrl -Owners $SiteCollAdmin
'''
command_result = execute_powershell_command(command_to_run)
if command_result.returncode != 0:
return ''
return user_onedrive_url
except Exception as e:
handle_global_exception(sys._getframe().f_code.co_name, e)
return ''
- Explanation:
- Retrieves the user's OneDrive URL via Microsoft Graph.
- Uses PnP PowerShell to assign the manager as the site owner.
- Requires certificate-based authentication for automation.
4. Assigning Mailbox Access to the Manager
The function grant_access_to_users_mailbox
uses PowerShell to grant the manager full access to the user's mailbox.
def grant_access_to_users_mailbox(terminated_user_email, manager_email):
try:
command_to_run = f'''
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -CertificateFilePath <CertPath> -AppID <AppId> -Organization <TenantName>
Add-MailboxPermission -Identity {terminated_user_email} -User {manager_email} -AccessRights FullAccess -InheritanceType All
'''
command_result = execute_powershell_command(command_to_run)
if command_result.returncode != 0:
return ''
return command_result
except Exception as e:
handle_global_exception(sys._getframe().f_code.co_name, e)
return None
- Explanation:
- Connects to Exchange Online using certificate-based authentication.
- Grants the manager full access to the terminated user's mailbox.
5. Methodology and Best Practices
- Automation: All steps are automated to reduce manual errors and speed up offboarding.
- Security: Uses certificate-based authentication for all automated PowerShell and Graph API calls.
- Separation of Duties: The terminated user's data is not deleted immediately, but access is reassigned to their manager for business continuity.
- Error Handling: All functions use a global exception handler to log and notify on errors.
6. Required Libraries and Tools
requests
for REST API callsmsal
for Microsoft authenticationldap3
for AD/LDAP operationsPnP.PowerShell
andExchangeOnlineManagement
PowerShell modules- Service principal with delegated permissions and certificate
7. Conclusion
Automating user deprovisioning in Microsoft 365 ensures compliance, security, and business continuity. By delegating OneDrive and mailbox access to managers, organizations can maintain access to critical data while protecting sensitive information.
Note:
- Replace placeholders like <SharePointRootUrl>
, <AppId>
, <TenantName>
, and <CertPath>
with your actual values.
- Always test automation in a non-production environment before rolling out to production.