Azure Active Directory: How to check device membership? - azure-active-directory

I'm trying to find a way to display all groups that an Intune device is a member of. I cannot find this function for the sake of my life. I don't see this fucntion under the Intune blade, nor the Azure Active Directory one. Is there any other way to see group memberships of a device?
PS: devices are managed via Intune and Azure AD only joined.
Tried to find the information via Microsoft and Powershell.
Get-AzureADDeviceMembership doesn't exist
I expect an output to display groups that an AAD device is a member of.

You can view the groups a device is a member of by searching for it from the Devices blade in Azure Active Directory.

I had the same problem and i was astonished that the Get-AzureADDeviceMembership cmdlet did not exists.
I used this as a work around:
Get-AzureADGroup -All 1 | ? {"COMPUTER_DISPLAY_NAME" -in (Get-AzureADGroupMember -ObjectId $_.ObjectId).DisplayName}
It works but is incredibly slow. So i also made a function which caches the groups and their member in a global variable. This functions runs instant from the second run since everything is cached.
function:
function Get-AzureADDeviceMembership{
[CmdletBinding()]
Param(
[string]$ComputerDisplayname,
[switch]$UseCache
)
if(-not $Global:AzureAdGroupsWithMembers -or -not $UseCache){
write-host "refreshing cache"
$Global:AzureAdGroupsWithMembers = Get-AzureADGroup -All 1 | % {
$members = Get-AzureADGroupMember -ObjectId $_.ObjectId
$_ | Add-Member -MemberType NoteProperty -Name Members -Value $members
$_
}
}
$Global:AzureAdGroupsWithMembers | % {
if($ComputerDisplayname -in ($_.Members | select -ExpandProperty DisplayName)){
$_
}
} | select -Unique
}
use the function:
Connect-AzureAD
Get-AzureADDeviceMembership -ComputerDisplayname "COMPUTER_DISPLAY_NAME" -UseCache

To add to Gerrit's answer, use -Filter groupTypes/any(c:c+ne+'Unified') with Get-AzureADGroup to filter out unified groups, as devices can't join them. This should speed up the query significantly.

Related

PowerShell ForEach Loop to Add UserPrincipalName and object ID to a file

I have a file of user emails. I need to gather their UPNs and object IDs.
Get-AzureADUser -Filter "PrimarySMTPAddress eq '$user.EmailAddress'"
I'm using this line to query AzureAD and it works perfectly. However when I place it in a loop I can't seem to get any data.
import-csv .\Book4.csv | ForEach-Object{
Get-AzureADUser -Filter "PrimarySMTPAddress eq '$_.EmailAddress'" | Select-Object UserPrincipalName, ObjectID
} | Export-Csv -Path .\Book4.csv -NoTypeInformation
Can anyone tell me where I'm going wrong. I thought this would be something simple but I've been stuck for an hour. The CSV file has three column headers: EmailAddress, UserPrincipalName, ObjectID
"PrimarySMTPAddress eq '$_.EmailAddress'" doesn't work as intended, because the attempted property access on variable $_, .EmailAddress, isn't effective:
Inside "...", an expandable string, you need $(...), the subexpression operator in order to access a variable's properties[1], call methods on it, or, more generally embed entire statements.
Therefore, use the following string instead:
"PrimarySMTPAddress eq '$($_.EmailAddress)'"
Also, you're mistakenly trying to read from and write back to the same file (.\Book4.csv) in the same pipeline, which doesn't work (without additional effort), as discussed in Allen Wu's helpful answer.
[1] Without enclosing in $(...), "...$_.EmailAddress..." cause $_ to be expanded by itself, whereas .EmailAddress is used verbatim. Compare Write-Output "$HOME.Length" to Write-Output "$($HOME.Length)", for instance.
#mklement0 is correct.
But another important thing is that we can't read from and write back to the same file in the same pipeline. Unless you make sure that the input file is read into memory, in full, before its lines are sent through the pipeline.
Use this:
$users = import-csv E:\temp\Book4.csv | ForEach-Object{
Get-AzureADUser -Filter "PrimarySMTPAddress eq '$($_.EmailAddress)'" | Select-Object UserPrincipalName, ObjectID
}
$users | Export-Csv -Path E:\temp\Book4.csv -NoTypeInformation

Powershell comparison for local network drive mappings against an array of drive mappings

I'm developing a PowerShell script for company drive mapping purposes. Currently, the script is getting the logged in username and querying AD to store their groups. From there, we are going to compare their AD groups to an array (mappings) and then map their drives accordingly.
The problem is, we don't want to tamper with their current drive mappings if they are already mapped properly (they match the mappings array letter/path). I've tried doing a compare, looping, etc but I can't seem to find a good method to compare the currently mapped Network Drive Letter/Path to the array and if it's the same, to disregard it.
Essentially, we don't want to disconnect network drives if the current mapping matches what's in the array.
$mappings = #(
[pscustomobject]#{adgroup='ADGROUP1';driveletter='G';networkpath='\\server\location1'}
[pscustomobject]#{adgroup='ADGROUP2';driveletter='H';networkpath='\\server\location2'}
[pscustomobject]#{adgroup='ADGROUP3';driveletter='I';networkpath='\\server\location3'}
[pscustomobject]#{adgroup='ADGROUP4';driveletter='J';networkpath='\\server\location4'}
)
$groups = Get-ADPrincipalGroupMembership $env:username | select name
$currentDrives = Get-PSDrive -PSProvider FileSystem | Select-Object Name, DisplayRoot | Where-Object {$_.DisplayRoot -ne $null}
foreach ($mapping in $mappings) {
if ($groups -match $mapping.adgroup) {
Remove-PSDrive -Name $mapping.driveletter -Force -ErrorAction SilentlyContinue
New-PSDrive -Name $mapping.driveletter -PSProvider FileSystem -Root $mapping.networkpath -Persist -Scope Global -ErrorAction SilentlyContinue | Out-Null
}
}
This is confusing because Get-PSDrive H will show the Root property being the network-mapped name. But (Get-PSDrive H).Root will return H:\. Weird, right?
You can use the DisplayRoot property to get the real network share:
If((Get-PSDrive $mapping.driveletter).DisplayRoot -ne $mapping.networkpath){
#un-map and re-map the drive
}

Extracting first and last names from txt file and using it to get username from AD and import it into csv

as a test and a way to get specific data from AD i am trying to get the data based on a txt file filled with names and last names of users. I worked out that using ConvertFrom-Stringcmdlet allows you to split names inside the txt file into two separate values, thus enabling you to use (in theory) Get-ADUser to find the user from AD and its attributes.
The code i was using so far is the following, with random changes here and there as i tried various options to make it work. I have been able to get the data i need by storing names under variables and then using the Get-ADUser cmdlet to pick them up from AD, i was even able to export that data into the CSV file. The issue is cant make it work when there is a text file filled with several entries.
Get-Content C:\temp\users.txt -encoding UTF8 |
ConvertFrom-String |
ForEach-Object {Get-ADUser -Filter {(givenName -Like '$($_.P1)') -and (sn -Like '$($_.P2)')} -Properties *} |
Select-object givenName, Surname, SamAccountName | Export-CSV C:\Temp\usersexport.csv -NoTypeInformation
Any help would be very appreciated.
You are using a sub-expression inside a non-expanding string. Check out Powershell's about_Quoting_Rules help topic for more detailed information. But, the short story is you need double quotes to expand something like $($_).
Something like:
Get-Content C:\temp\users.txt -encoding UTF8 |
ConvertFrom-String |
ForEach-Object {Get-ADUser -Filter "( givenName -like '$($_.P1)' ) -and (sn -like '$($_.P2)' )" -Properties *} |
Select-object givenName, Surname, SamAccountName | Export-CSV C:\Temp\usersexport.csv -NoTypeInformation
Notice that I quoted the entire filter. Technically Get-ADUser's -Filter parameter takes a string so this is acceptable and makes it a little easier to read.
Also note: you may need "*" to make this work correctly. Technically -like will work on exact matches, but it's more typically used when searching with wildcards. In your case using '*$($_.P1)*' might help get you past the issue.
If you are confident in the values especially considering you are also using the -and operator you might think about using -eq. However I'd be concerned as there's always a chance of common name collisions. For example in the US there could easily be 2 John Smiths in AD...
I'd also point out it's more expedient to use Import-Csv for this. When corrected your approach is working, but below is more readable and easier to write in the first place:
Example with -eq:
Import-Csv -Path C:\temp\users.txt -header "givenName","sn" -Delimiter " " |
ForEach-Object{
$GivenName = $_.givenName
$LastName = $_.sn
ForEach-Object { Get-ADUser -Filter "(givenName -eq '$GivenName') -and (sn -eq '$LastName')" -Properties * }
} |
Select-Object givenName, Surname, SamAccountName |
Export-CSV C:\Temp\usersexport.csv -NoTypeInformation
Example with -like and Wildcards:
Import-Csv -Path C:\temp\users.txt -header "givenName","sn" -Delimiter " " |
ForEach-Object{
$GivenName = $_.givenName
$LastName = $_.sn
ForEach-Object { Get-ADUser -Filter "(givenName -like '*$GivenName*') -and (sn -like '*$LastName*')" -Properties * }
} |
Select-Object givenName, Surname, SamAccountName |
Export-CSV C:\Temp\usersexport.csv -NoTypeInformation
You also may want to avoid -Properties * and instead define a more exact set of properties to retrieve. In bigger jobs that's going to make a performance difference.
Oh and, you usually don't need to specify the encoding for Get-Content it's very good at figuring that out on it's own.
In PowerShell Core the default value for the parameter is UTF8NoBOM. NoBOM just means there's no "Byte Order Mark" declaring the encoding and so it shouldn't have any issues with a UTF8 file. In Windows PowerShell 5.1 you may need to specify as you have.
It looks like this is a learning exercise for you, let me know if this helps.

Export Members in AzureAD Group

Running script to export all Members in a specific AzureAD Group, but only get half and not all users.
I verified that there are members in Azure Portal, but export only gives me half
This is the script I ran:
Get-AzureADgroupmember -objectid "xxxxxxxxxxxxxxxxxxxxxx" | get-azureaduser | Export-Csv -path C:\temp\memberexport.csv
Any reason on why this is exporting only half and not all users in group?
Thank you,
When you don't specify -All as well as -Top optional parameters, then Get-AzureADGroupMember command may return you only a default number of records (like say 100. I'm not sure on this exact number).
So if you want all the members, try to specify that explicitly by using -All parameter. Example below:
Get-AzureADgroupmember -objectid "xxxxxxxxxxxxxxxxxxxxxx" -All $true | get-azureaduser | Export-Csv -path C:\temp\memberexport.csv

Is it possible to make IndexOf case-insensitive in PowerShell?

I've got a problem searching an INDEX in an array made up by query sessions command in a terminal server.
This is the problematic script:
# Array of logged users in terminal servers
$a=Get-RDUsersession -CollectionName "BLABLA" -ConnectionBroker BLABLA.BLA.BL
# Array of all users with two columns from active directory
$b=Get-ADUser -filter * -properties TelephoneNumber,SamAccountName
Now imagine logging in the terminal server using the account name TEST instead of test.
If I do:
$c = $b[$b.SamAccountName.indexof("test")].TelephoneNumber
then I don't get the telephone number.
I think that's because of the case sensitivity, isn't it? If I type TEST in the search command, I get the correct number.
Is there any simple way to solve this problem and make the search of the index case-insensitive?
I've read about using the method [StringComparison]"CurrentCultureIgnoreCase", but it seems not working with array.
Thanks.
Since $b is an Object[] type, then you would probably want to do a Where-Object.
$b | Where-Object -FilterScript {$_.Samaccountname -like '*Smith*'} | Select-Object -ExpandProperty 'telephoneNumber'
That being said, an array in Powershell can be indexed case-insensitively if it is converted to a [Collections.Generic.List[Object]] type.
$b = [Collections.Generic.List[Object]]$b
$b.FindIndex( {$args[0].sAMAccountName -eq 'test'} )
Note that pulling every single user object in AD and filtering using where-object or index matching can be very slow. You can instead Get-ADUser as needed or pull all ADusers using a filter that pulls only the users returned in $a.
If you insist on having all ADUsers in one spot with one pull, consider looping over the list once to make a hash lookup so you can easily index the hash value.
#Create account lookup hash
$accountlookup = #{}
foreach ($element in $accounts) {
$accountlookup[$element.SamAccountName] = $element
}
Hope that helps!

Resources