Public/Remove-TcAccess.ps1
|
function Remove-TcAccess { <# .SYNOPSIS Removes the applications of TenantConverge from the tenants of a project. .DESCRIPTION Deletes the TenantConverge Read-Only application and the delegated TenantConverge PnP application from each tenant, forgets their identifiers in the local access file, and removes the certificate from this computer when no tenant uses it any more. Entra ID keeps a deleted application for 30 days. An application is deleted only when it carries the name TenantConverge gave it and its ID is in the access file. Any other application stays in the tenant, and the command says so: one of the same name that this project did not create, and a PnP client ID that was typed in for another application. It writes to the tenant, as Initialize-TcAccess does, and as Invoke-TcRemediation and Undo-TcRemediation do with -Apply. It asks for confirmation. Use -WhatIf to see what it would do. .PARAMETER Project The project file. .PARAMETER Tenant The roles to clean up. The default is the target and every source. .PARAMETER UseDeviceCode Signs in with a device code instead of a browser window. .EXAMPLE Remove-TcAccess -Project ./project.json Removes the applications from every tenant of the project. .EXAMPLE Remove-TcAccess -Project ./project.json -Tenant S2 -WhatIf Shows what would be removed from S2, and changes nothing. #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param( [Parameter(Mandatory)][string]$Project, [ValidateSet('Target', 'S1', 'S2', 'S3')][string[]]$Tenant, [switch]$UseDeviceCode ) $projectPath = Resolve-TcPath -Path $Project Initialize-TcSession -Project (Read-TcProjectFile -Path $projectPath) -Access (Read-TcAccessFile -ProjectPath $projectPath) $chosen = @(if ($Tenant) { $Tenant | Where-Object { $script:TcTenants.Contains($_) } } else { $script:TcTenants.Keys }) if ($chosen.Count -eq 0) { throw 'No tenant of this project matches -Tenant.' } foreach ($role in $chosen) { $entry = $script:TcTenants[$role] $target = "$($entry['displayName']) ($($entry['primaryDomain']))" if (-not $PSCmdlet.ShouldProcess($target, "Delete the applications '$script:TcApplicationName' and '$script:TcPnpApplicationName'")) { continue } $tenantId = Resolve-TcTenantId -Tenant $entry Connect-TcGraphAdmin -Tenant $entry -TenantId $tenantId -UseDeviceCode:$UseDeviceCode $deleted = [System.Collections.Generic.List[string]]::new() $access = Get-TcProperty $entry 'access' $created = @((Get-TcProperty $access 'clientId'), (Get-TcProperty $access 'pnpClientId')) | Where-Object { $_ } foreach ($name in $script:TcApplicationName, $script:TcPnpApplicationName) { foreach ($application in @(Get-TcAccessGraphFilter -Collection 'applications' -Filter "displayName eq '$name'")) { if ([string]$application['appId'] -notin $created) { Write-TcMessage -Message "The application '$name' ($($application['appId'])) is not one this project created, so it stays in this tenant." -Level Warning continue } Invoke-TcAccessGraph -Method DELETE -Uri "v1.0/applications/$($application['id'])" | Out-Null $deleted.Add([string]$application['appId']) Write-TcMessage -Message "Application '$name' ($($application['appId'])) deleted. Entra ID keeps it for 30 days." -Level Success } } $pnpClientId = Get-TcProperty $access 'pnpClientId' if ($pnpClientId -and $pnpClientId -notin $deleted) { Write-TcMessage -Message "The PnP application $pnpClientId is not named '$script:TcPnpApplicationName', so it stays in this tenant. Delete it by hand if nothing else uses it." -Level Warning } Write-TcAccessEntry -ProjectPath $projectPath -Role $role -Entry $null Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null } if (-not $WhatIfPreference -and (Read-TcAccessFile -ProjectPath $projectPath).Count -eq 0) { Remove-TcReadCertificate } } function Remove-TcReadCertificate { <# .SYNOPSIS Removes the read-only certificate from the certificate store of the current user. #> [CmdletBinding(SupportsShouldProcess)] param() foreach ($certificate in @(Get-ChildItem Cert:\CurrentUser\My | Where-Object Subject -EQ $script:TcCertificateSubject)) { if ($PSCmdlet.ShouldProcess($certificate.Thumbprint, 'Delete the certificate and its key')) { Remove-Item -LiteralPath "Cert:\CurrentUser\My\$($certificate.Thumbprint)" -DeleteKey Write-TcMessage -Message "Certificate $($certificate.Thumbprint) removed from this computer." -Level Success } } } |