user management
4 TopicsAzure DevOps - How to collect all accounts from Organization using PowerShell
When you are managing an Azure DevOps instance, you can have one or many Organizations (depending of your isolation and distribution requirements). Each organization will have a specific Account list (with license associated), but there is no automatic cleanup to remove disable accounts or consolidate all account in one view, and the built-in CSV Export module is limited in usage. This PowerShell Script will connect to all organization you specified in setting (using a dedicated Token you have to use or dedicated per Organization) to get all declared accounts, and loop for each account the Project part of. If No project assigned, you will have "NO PROJECT" as value. Import-module AzureAD connect-azureAD #region -- Customized Script Settings (need to be reviewed) --- # ================== / Parameters to Adapt \ ================== [string]$SharePointTeamSite = "https://tenant.sharepoint.com/sites/YourCollection/" [string]$DocumentLibrary = "YourDocLib" [string]$GlobalPATForAllORganizations= "xxxyyyyxxxxxxyyyyy" #If you have a global PAT [string]$JSonFolderPath = "C:\JSONDEVOPS" [string]$DomainNameEmail = "@emaildomain.com" # ================== \ Parameters to Adapt / ================== #endregion #region -- Internal Script Settings --- $OrganizationList = @() [string]$PAT = "" [string]$OrganizationName = "" [string]$Organization = "" [string]$UserGroupJSonFilePath = "" [string]$UserListJSonFilePath = "" [string]$AccountValidInAzureAD = "" $DataRefreshDate = Get-Date -Format "yyyy-MM-dd" [string]$TempEmailAddress = "" $UserGroupsOveralOrganization = @() $UserGroupOveralOragnizationJSonFilePath = "$JSonFolderPath\DevOps-UserGroups.json" #endregion #region -- Each Az DevOps Organization -- #YourOrganization1 $PAT = $GlobalPATForAllORganizations #If specific https://dev.azure.com/YourOrganization1/_usersSettings/tokens $OrganizationName = "YourOrganization1" $OrganizationWithPAT = New-Object PSObject -property @{OrganizationName=$OrganizationName;OrganizationPAT=$PAT} $OrganizationList += $OrganizationWithPAT #YourOrganization2 $PAT = $GlobalPATForAllORganizations #If specific https://dev.azure.com/YourOrganization2/_usersSettings/tokens $OrganizationName = "YourOrganization2" $OrganizationWithPAT = New-Object PSObject -property @{OrganizationName=$OrganizationName;OrganizationPAT=$PAT} $OrganizationList += $OrganizationWithPAT #YourOrganization3 $PAT = $GlobalPATForAllORganizations #If specific https://dev.azure.com/YourOrganization3/_usersSettings/tokens $OrganizationName = "YourOrganization3" $OrganizationWithPAT = New-Object PSObject -property @{OrganizationName=$OrganizationName;OrganizationPAT=$PAT} $OrganizationList += $OrganizationWithPAT #endregion foreach($MyOrganization in $OrganizationList) { $Organization = "https://dev.azure.com/$($MyOrganization.OrganizationName)/" $UserGroupsPerOrganization = @() $UserGroupJSonFilePath = "$JSonFolderPath\$($MyOrganization.OrganizationName)-UserGroups.json" $UserListJSonFilePath = "$JSonFolderPath\$($MyOrganization.OrganizationName)-UsersList.json" echo $($MyOrganization.OrganizationPAT) | az devops login --org $Organization az devops configure --defaults organization=$Organization $allUsers = az devops user list --org $Organization --top 10000 | ConvertFrom-Json #write-host "All Users:", $allUsers $allUsers | ConvertTo-Json | Out-File -FilePath $UserListJSonFilePath foreach($au in $allUsers.members) { if($au.user.mailAddress.endswith($DomainNameEmail)) { $TempEmailAddress = $au.user.mailAddress -replace "'", "''" $MyAzureADUser = Get-AzureADUser -Filter "userPrincipalName eq '$($TempEmailAddress)'" if($MyAzureADUser) { if($MyAzureADUser.AccountEnabled) { $AccountValidInAzureAD = "ACCOUNT VALID IN AZURE AD" } else { $AccountValidInAzureAD = "ACCOUNT DISABLE IN AZURE AD" } } else { $AccountValidInAzureAD = "ACCOUNT NOT EXIST IN AZURE AD" } } else { $AccountValidInAzureAD = "ACCOUNT NOT INTERNAL EMAIL" } $activeUserGroups = az devops security group membership list --id $au.user.principalName --org $Organization --relationship memberof | ConvertFrom-Json [array]$groups = ($activeUserGroups | Get-Member -MemberType NoteProperty).Name if ($groups.count -gt 0) { foreach ($aug in $groups) { $UserGroupsPerOrganization += New-Object -TypeName PSObject -Property @{ DevOpsOrganizationName=$MyOrganization.OrganizationName principalName=$au.user.principalName displayName=$au.user.displayName mailAddress=$au.user.mailAddress UserID=$au.id AccountValidInAzureAD = $AccountValidInAzureAD LicenseType=$au.accessLevel.licenseDisplayName dateCreated=$au.dateCreated lastAccessedDate=$au.lastAccessedDate ProjectName= $($activeUserGroups.$aug.principalName.Split("\\"))[0] GroupName=$activeUserGroups.$aug.principalName DataRefreshDate = $DataRefreshDate } } } else { $UserGroupsPerOrganization += New-Object -TypeName PSObject -Property @{ DevOpsOrganizationName=$MyOrganization.OrganizationName principalName=$au.user.principalName displayName=$au.user.displayName mailAddress=$au.user.mailAddress UserID=$au.id AccountValidInAzureAD = $AccountValidInAzureAD LicenseType=$au.accessLevel.licenseDisplayName dateCreated=$au.dateCreated lastAccessedDate=$au.lastAccessedDate ProjectName= "[NO PROJECT]" GroupName="[NO PROJECT GROUP]" DataRefreshDate = $DataRefreshDate } } } $UserGroupsPerOrganization | ConvertTo-Json | Out-File -FilePath $UserGroupJSonFilePath $UserGroupsOveralOrganization += $UserGroupsPerOrganization } $UserGroupsOveralOrganization | ConvertTo-Json | Out-File -FilePath $UserGroupOveralOragnizationJSonFilePath Import-Module PnP.PowerShell -DisableNameChecking Connect-PnPOnline -Url $SharePointTeamSite -UseWebLogin $Files = Get-ChildItem -Path $JSonFolderPath -Force -Recurse #Upload All files from the directory ForEach ($File in $Files) { Write-host "Uploading $($File.Directory)\$($File.Name)" #upload a file to sharepoint online using powershell - Upload File and Set Metadata Add-PnPFile -Path "$($File.Directory)\$($File.Name)" -Folder $DocumentLibrary -Values @{"Title" = $($File.Name)} } The result will be a JSON file (saved in SharePoint), you can easily load in Power Bi to build your dedicated Report helping you to adapt Develop license with real usage like: Remove all accounts Disable in Azure AD Downgrade all account license from Basic+ to Stakeholder if no connection since more than 1 year Remove all accounts without any project Any other rules part of your Governance model That could also be adapted to use an Azure Engine to cleanup automatically your Organization. In any case, that part need to be integrated into your FinOps process to optimize your license costs as you really need and use. Fabrice Romelard References used to build that script: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-windows?view=azure-cli-latest&tabs=azure-powershell https://vinijmoura.medium.com/how-to-list-all-users-and-group-permissions-on-azure-devops-using-azure-devops-cli-54f73a20a4c7 Update: Script cleaned to be easily modified and used8.7KViews2likes3CommentsBest practice for changing domain user name
Hi folks, What is the current best practice with Windows Server 2016 domain functional level to handle user name change? Changing the UPN seems a bit risky. Do we have a best practice on how to handle the situation where user has changed their last name and wants to have the new last name in email address, display name and login UPN. If UPN is changed, how likely is everything from SharePoint permissions, Teams channels and to other 3rd party software depending on Azure AD authentication to break down and burn in fire? Thanks for your reply! TommiSolved50KViews0likes6CommentsAnyone not able to add new members/guests or even channels in the new Teams preview?
I don't see any way for me to add new members or guests to my teams (I'm the owner). Right clicking menu shows only a few options, namely "manage team" which also have no clear way of adding members. Anyone else dealing with this? Seriously, it's like 4 steps forward 5 steps back. I know it's a preview, but the above are simple core features. Really wanted to use this preview so I can easily switch between organizations. Looks like MS365 is not ready for this yet, I'll be considering alternatives.