1+ <# ##################################################
2+ # #
3+ # Copyright (c) Microsoft. All rights reserved. #
4+ # #
5+ ##################################################>
6+
7+ $DefaultAdminSubscriptionName = " Default Provider Subscription"
8+
9+ <#
10+ . Synopsis
11+ Clear the portal user data
12+ #>
13+ function Clear-AzsUserData
14+ {
15+ param
16+ (
17+ # The directory tenant identifier of Azure Stack Administrator.
18+ [Parameter (Mandatory = $true )]
19+ [ValidateNotNullOrEmpty ()]
20+ [string ] $AzsAdminDirectoryTenantId ,
21+
22+ # The Azure Stack ARM endpoint URI.
23+ [Parameter (Mandatory = $true )]
24+ [ValidateNotNullOrEmpty ()]
25+ [Uri ] $AzsAdminArmEndpoint ,
26+
27+ # The user principal name of the account who's user data should be cleared.
28+ [Parameter (Mandatory = $true )]
29+ [ValidateNotNullOrEmpty ()]
30+ [string ] $UserPrincipalName ,
31+
32+ # Optional: The directory tenant identifier of account who's user data should be cleared.
33+ # If it is not specified, it will delete all the
34+ [Parameter (Mandatory = $false )]
35+ [ValidateNotNullOrEmpty ()]
36+ [string ] $DirectoryTenantId ,
37+
38+ # Indicate whether it is ADFS env or not
39+ [switch ] $ADFS ,
40+
41+ # Optional: A credential used to authenticate with Azure Stack. Must support a non-interactive authentication flow. If not provided, the script will prompt for user credentials.
42+ [ValidateNotNull ()]
43+ [pscredential ] $AutomationCredential = $null
44+ )
45+ # requires -Version 4.0
46+ # requires -Module "AzureRM .Profile "
47+ # requires -Module "Azs .Subscriptions .Admin "
48+ # requires -RunAsAdministrator
49+
50+ $ErrorActionPreference = ' Stop'
51+ $VerbosePreference = ' Continue'
52+
53+ Import-Module $PSScriptRoot \..\..\Identity\GraphAPI\GraphAPI.psm1 - Force
54+ Import-Module $PSScriptRoot \..\..\Identity\AzureStack.Identity.Common.psm1 - Force
55+
56+ Write-Verbose " Login to Azure Stack Admin ARM..." - Verbose
57+ $AzsAdminEnvironmentName = " AzureStackAdmin"
58+ $adminArmEnv = Initialize-AzureRmEnvironment - AdminResourceManagerEndpoint $AzsAdminArmEndpoint - DirectoryTenantId $AzsAdminDirectoryTenantId - EnvironmentName $AzsAdminEnvironmentName
59+ Write-Verbose " Created admin ARM env as $ ( ConvertTo-JSON $adminArmEnv ) " - Verbose
60+
61+ $params = @ {
62+ AzureEnvironment = $adminArmEnv
63+ SubscriptionName = $DefaultAdminSubscriptionName
64+ }
65+ if ($AutomationCredential )
66+ {
67+ $params.AutomationCredential = $AutomationCredential
68+ }
69+ $refreshToken = Initialize-AzureRmUserRefreshToken @params
70+ Write-Verbose " Login into admin ARM and got the refresh token." - Verbose
71+
72+ $adminSubscriptionId = (Get-AzureRmSubscription - Verbose | where { $_.Name -ieq $DefaultAdminSubscriptionName }).Id
73+ Write-Verbose " Get default Admin subscription id $adminSubscriptionId ." - Verbose
74+
75+ if ($DirectoryTenantId )
76+ {
77+ $directoryTenantIdsArray = [string []]$DirectoryTenantId
78+ }
79+ else
80+ {
81+ Write-Verbose " Input parameter 'DirectoryTenantId' is empty. Retrieving all the registered tenant directory..." - Verbose
82+ $directoryTenantIdsArray = (Get-AzsDirectoryTenant - Verbose).TenantId
83+ }
84+
85+ Write-Host " Clearing the user data with input user principal name $UserPrincipalName and directory tenants '$DirectoryTenantIdsArray '..."
86+
87+ $clearUserDataResults = @ () # key is directory Id, value is clear response
88+
89+ $initializeGraphEnvParams = @ {
90+ RefreshToken = $refreshToken
91+ }
92+ if ($ADFS )
93+ {
94+ $initializeGraphEnvParams.AdfsFqdn = (New-Object Uri $adminArmEnv.ActiveDirectoryAuthority ).Host
95+ $initializeGraphEnvParams.GraphFqdn = (New-Object Uri $adminArmEnv.GraphUrl ).Host
96+
97+ $QueryParameters = @ {
98+ ' $filter' = " userPrincipalName eq '$ ( $UserPrincipalName.ToLower ()) '"
99+ }
100+ }
101+ else
102+ {
103+ $graphEnvironment = Resolve-GraphEnvironment - AzureEnvironment $adminArmEnv
104+ Write-Verbose " Resolve the graph env as '$graphEnvironment '" - Verbose
105+ $initializeGraphEnvParams.Environment = $graphEnvironment
106+
107+ $QueryParameters = @ {
108+ ' $filter' = " userPrincipalName eq '$ ( $UserPrincipalName.ToLower ()) ' or startswith(userPrincipalName, '$ ( $UserPrincipalName.Replace (" @" , " _" ).ToLower()) ')"
109+ }
110+ }
111+
112+ foreach ($dirId in $directoryTenantIdsArray )
113+ {
114+ Write-Verbose " Intializing graph env..." - Verbose
115+ Initialize-GraphEnvironment @initializeGraphEnvParams - DirectoryTenantId $dirId
116+ Write-Verbose " Intialized graph env" - Verbose
117+
118+ Write-Verbose " Querying all users..." - Verbose
119+ $usersResponse = Invoke-GraphApi - ApiPath " /users" - QueryParameters $QueryParameters
120+ Write-Verbose " Retrieved user object as $ ( ConvertTo-JSON $usersResponse.value ) " - Verbose
121+
122+ $userObjectId = $usersResponse.value.objectId
123+ Write-Verbose " Retrieved user object Id as $userObjectId " - Verbose
124+ if (-not $userObjectId )
125+ {
126+ Write-Warning " There is no user '$UserPrincipalName ' under directory tenant Id $dirId ."
127+ $clearUserDataResult += [pscustomobject ]@ {
128+ DirectoryTenantId = $dirId
129+ UserPrincipalName = $UserPrincipalName
130+ ErrorMessage = " User not found in directory."
131+ }
132+ continue
133+ }
134+ elseif (([string []]$userObjectId ).Length -gt 1 )
135+ {
136+ Write-Warning " There is one more users retrieved with '$UserPrincipalName ' under directory tenant Id $dirId ."
137+ $clearUserDataResult += [pscustomobject ]@ {
138+ DirectoryTenantId = $dirId
139+ UserPrincipalName = $UserPrincipalName
140+ ErrorMessage = " One more user accounts found in directory. User principal name may be incorrect. "
141+ }
142+ continue
143+ }
144+ else
145+ {
146+ $params = @ {
147+ AzsEnvironment = $adminArmEnv
148+ UserObjectId = $userObjectId
149+ DirectoryTenantId = $dirId
150+ AdminSubscriptionId = $adminSubscriptionId
151+ AzsAdminArmEndpoint = $AzsAdminArmEndpoint
152+ }
153+ $curResult = Clear-SinglePortalUserData @params
154+ $clearUserDataResult += @ ( $curResult )
155+ }
156+ }
157+
158+ return $clearUserDataResult
159+ }
160+
161+ function Clear-SinglePortalUserData
162+ {
163+ param
164+ (
165+ # The user credential with which to acquire an access token targeting Graph.
166+ [Parameter (Mandatory = $true )]
167+ [ValidateNotNull ()]
168+ [Microsoft.Azure.Commands.Profile.Models.PSAzureEnvironment ] $AzsEnvironment ,
169+
170+ [Parameter (Mandatory = $true )]
171+ [ValidateNotNull ()]
172+ [string ] $UserObjectId ,
173+
174+ [Parameter (Mandatory = $true )]
175+ [ValidateNotNull ()]
176+ [string ] $DirectoryTenantId ,
177+
178+ [Parameter (Mandatory = $true )]
179+ [ValidateNotNull ()]
180+ [string ] $AdminSubscriptionId ,
181+
182+ # The Azure Stack ARM endpoint URI.
183+ [Parameter (Mandatory = $true )]
184+ [ValidateNotNull ()]
185+ [Uri ] $AzsAdminArmEndpoint
186+ )
187+
188+ try
189+ {
190+ Write-Verbose " Retrieving access token..." - Verbose
191+ $accessToken = (Get-GraphToken - Resource $AzsEnvironment.ActiveDirectoryServiceEndpointResourceId - UseEnvironmentData).access_token
192+
193+ $clearUserDataEndpoint = " $AzsAdminArmEndpoint /subscriptions/$AdminSubscriptionId /providers/Microsoft.PortalExtensionHost.Providers/ClearUserSettings?api-version=2017-09-01-preview"
194+ $headers = @ {
195+ Authorization = " Bearer $accessToken "
196+ " Content-Type" = " application/json"
197+ }
198+ $payload = @ {
199+ UserObjectId = $UserObjectId
200+ DirectoryTenantId = $DirectoryTenantId
201+ }
202+ $httpPayload = ConvertTo-Json $payload - Depth 10
203+ Write-Verbose " Clearing user data with URI '$clearUserDataEndpoint ' and payload: `r`n $httpPayload ..." - Verbose
204+ $clearUserDataResponse = $httpPayload | Invoke-RestMethod - Headers $headers - Method POST - Uri $clearUserDataEndpoint - TimeoutSec 120 - Verbose
205+
206+ return [pscustomobject ]@ {
207+ DirectoryTenantId = $DirectoryTenantId
208+ UserPrincipalName = $UserPrincipalName
209+ ResponseData = $clearUserDataResponse
210+ }
211+ }
212+ catch
213+ {
214+ if ($_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode ]::NotFound -and (ConvertFrom-JSON $_.ErrorDetails.Message ).error.code -eq " NoPortalUserData" )
215+ {
216+ Write-Warning " No user data with user object Id and directory tenant Id"
217+ return [pscustomobject ]@ {
218+ DirectoryTenantId = $DirectoryTenantId
219+ UserPrincipalName = $UserPrincipalName
220+ ErrorMessage = " No portal user data"
221+ }
222+ }
223+ else
224+ {
225+ Write-Warning " Exception when clear user data with user object Id and directory tenant Id: $_ `r`n $ ( $_.Exception ) "
226+ return [pscustomobject ]@ {
227+ DirectoryTenantId = $DirectoryTenantId
228+ UserPrincipalName = $UserPrincipalName
229+ ErrorMessage = " Exception when clearing user data"
230+ Exception = $_.Exception
231+ }
232+ }
233+ }
234+ }
235+
236+ Export-ModuleMember - Function Clear-AzsUserData
0 commit comments