Verify if a disabled user account has a shared mailbox - azure-active-directory

A co-worker and I are trying to develop a script that will show us shared mailboxes attached to a disabled user account and when the account was disabled by looking at the Last password change date time property on their AD account in Azure. When we run this half the time it only grabs the info for the shared mailboxes attached to disabled user the other it pulls no data to the csv. Any help is appreciated.
$DisabledUsers = Get-AzureADUser -Filter {(Enabled -eq $False)} | Select-Object Lastpasswordchangedatetime
$SharedInboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox $Results = #()
Foreach ($SharedInbox in $SharedInboxes)`
{
  $InboxPermissions = Get-MailboxPermission -Identity $SharedInbox.Identity | Where-Object {$_.User.ToString().Split("\")[1] -in $DisabledUsers}
  If ($InboxPermissions)
  {
    $Result = [PSCustomObject]#{
      SharedInbox = $SharedInbox.Identity
      DisabledUser = $InboxPermissions.User.ToString().Split("\")[1]
    }
    $Results += $Result
  }
} $Results | Export-Csv -Path "C:\SharedInboxforDisabledAccounts.csv" -NoTypeInformation
Expected a csv to generate with the mailboxes attached to disabled users and the date the password was last changed on the account indicating when the user was disabled

Related

Bulk adding users to AzureAD Script error

The goal of the script is to run and add all users with a specific job title to an AzureAD Group.
I've tested the variable and it grab the right people and will display if I write the variable to the screen.
The error message I get states "ADD-AzureADGroupMember : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter.
#Grab all users with the job title IT Support Technician
$User = (Get-AzureADUser -All $true |
Where-Object -FilterScript {$_.JobTitle -eq "IT Support Technician"}).ObjectId
#Grab the ObjectID of the AzureADGroup
$Branch = (Get-AzureADGroup -SearchString "Test SG").ObjectId
#Add each of the Users to the AzureADGroup
$User | ForEach-Object {
Add-AzureADGroupMember -ObjectId $Branch -RefObjectId $User
}
You're iterating over $user then trying to add all users within your Foreach-Object loop.
To reference the current pipeline item you can use $_ or $PSItem
$User | ForEach-Object {
Add-AzureADGroupMember -ObjectId $Branch -RefObjectId $_
}
Documentation on Automatic Variables
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-7.2#_

Exporting Multi-Valued Attributes in PowerShell to Excel - Attempting to Automate Using an Array of Hash Tables

I am trying to automate the unwrapping of multi-valued attributes in PowerShell for the purpose of exporting the information to an excel sheet. The known solution for enabling multi-valued exporting to excel is to manually create a hash table for each multi-valued attribute, which works just well. Example:
Get-ADForest -Server <servername> |
Select-Object #{Name='ApplicationPartitions';Expression={$.ApplicationPartitions}},
DomainNamingMaster,
#{Name="Domains";Expression={$.Domains}},
ForestMode,
#{Name="GlobalCatalogs";Expression={$.GlobalCatalogs}},
Name,
PartitionsContainer,
RootDomain,
SchemaMaster,
#{Name="Sites";Expression={$.Sites}} |
Export-Csv $home'AD Forest Information.csv'
However, I would like to automate this for commands that have many multi-valued attributes. Here is what I have so far (I am using Get-ADForest for testing):
$Objects = #()
$Object = #{}
Get-ADForest | Get-Member | Where-Object {$_.membertype -eq 'property'} |
Select-Object Name |
ForEach-Object {$Object = #{Name=$_.Name;Expression="$" + "_" + "." + $_.Name} ; $Objects +=$Object}
Write-Output $Objects
Get-ADForest -Server <servername> | Select-Object $Objects | Export-Csv $home\'AD Forest Information.csv'
The issue is that the exported .csv has the correct column titles, but the values of the attributes are still Microsoft.ActiveDirectory.Management.ADPropertyValueCollection like they would be without unwrapping the attribute.
Please let me know if you have any questions.
Any suggestions would be awesome.
Thank you!
Austin
Try this for your example, let me know if this is what you expect as output for your csv:
cd $Home\Documents
function parseADObject{
param(
[cmdletbinding()]
[parameter(mandatory,valuefrompipeline)]
$InputObject
)
$properties=($inputObject|gm -MemberType Property).Name
$parsedObject=#{}
foreach($prop in $Properties)
{
$thisProp=$inputObject.$prop
if($thisProp -and $thisProp.GetType() -match 'Collection|\[]')
{
$val=($inputObject.$prop|out-string).Trim()
}
elseif($thisProp -and $thisProp.GetType() -match 'Int|Boolean|Double')
{
$val=$thisProp
}
elseif($thisProp)
{
$val=($thisProp.ToString()).Trim()
}
else
{
$val=$null
}
$parsedObject.$prop=$val
}
return $parsedObject|%{New-Object PSObject -Property $_}
}
Get-ADForest|parseADObject|Export-Csv test.csv -NoTypeInformation;ii test.csv
Explanation, I'm gonna use ADForest for this example:
First you get the properties of the object you want to parse:
$adforest=Get-ADForest
PS C:\> $properties=($adforest|gm -MemberType Property).Name
PS C:\> $properties
ApplicationPartitions
CrossForestReferences
DomainNamingMaster
Domains
ForestMode
GlobalCatalogs
Name
PartitionsContainer
RootDomain
SchemaMaster
Sites
SPNSuffixes
UPNSuffixes
Then you loop on the properties of your object asking for the type of object:
PS C:\> foreach($prop in $properties){$adforest.$prop.gettype()}
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False ADPropertyValueCollection System.Collections.CollectionBase
True False ADPropertyValueCollection System.Collections.CollectionBase
True True String System.Object
True False ADPropertyValueCollection System.Collections.CollectionBase
True True ADForestMode System.Enum
True False ADPropertyValueCollection System.Collections.CollectionBase
True True String System.Object
True True String System.Object
True True String System.Object
True True String System.Object
True False ADPropertyValueCollection System.Collections.CollectionBase
True False ADPropertyValueCollection System.Collections.CollectionBase
True False ADPropertyValueCollection System.Collections.CollectionBase
And then you're just asking what type of object it is:
If the type matches 'Collection or []' then you're passing the value of that property to Out-String this is useful for properties like proxyAddresses on the AD Users.
ElseIf the type matches a Boolean or Integer or Double then you're leaving the value as is without any changes.
ElseIf the the property has any Value, meaning, is not $null, I'm using the ToString() method. This is useful for properties like ObjectGUID or ObjectSID
Notice I'm using Trim() each time I use Out-String or ToString() to eliminate any empty blank spaces at the beginning or the end
The value of each property loop, stored in the $val variable is then being added to the hashTable $parsedObject and then after looping is finished the variable is being converted to a PSObject (if you don't do this the export will not show as you expect it, it will show the type of the values instead of the actual data).

Working with Arrays / GetWebVirtualDirectory in PowerShell

I am new to PowerShell, so I got this far
$sites = Get-Website
$OrderSite = $sites | Where Name -eq 'SiteName'
$directories = Get-WebVirtualDirectory -Site $OrderSite.Name
So that $directories looks like
Name Physical Path
---- -------------
Profile C:\Path1
WebMain C:\Path1
Now I am stuck
$directories[0] =
Name Physical Path
---- -------------
Profile C:\Path1
But $directories[0].Name, $directories[0]["Name"], $directories |Where Name -eq 'Profile', $directories |Where Name -like 'P*' and $directories | ForEach {$_.Name } are all null
However, $directories | ForEach {$_ } and $directories |Where Name -like '*'
Return the full list.
So what is the correct way to filter or Access the property Name or how do I verify what the names or properties of my array real are?
Unfortunately I can't test this as no IIS Provider on my PC.
I believe this will get you what you're after, based on what works and doesn't work in the question:
$directories | Where-Object {Path -eq 'Profile'}
Where-Object expects a statement {...}

List of users to match a list of job titles in AD

I have a list of Job titles in a csv file and need to match these to whichever user has the title in AD.
CSV Contents is like this:
JobTitle1
JobTitle2
JobTitle3
The following command will work to get a list of all users with the JobTitle1 title:
Get-ADUser -Filter "Title -like 'JobTitle1'"
However I can't get this to work with the CSV file as an array, it doesnt return any output:
$Titles = Get-Content -Path "c:\jobtitles.csv"
ForEach ($Title In $Titles)
{
Get-ADUser -Filter {Title -like '$Title'}
}
In PowerShell a variable within single quotes doesn't get populated so you have to use double quotes instead - or just omit them:
$Titles = Get-Content -Path "c:\jobtitles.csv"
ForEach ($Title In $Titles)
{
Get-ADUser -Filter {Title -like $Title}
}

LDAP group membership (including Domain Users)

How can I get a list of users within an LDAP group, even if that group happens to be the primary group for some users?
For example, suppose "Domain Users" is "Domain Leute" in German. I want all members of "CN=Domain Leute,DC=mycompany,DC=com". How would I know that is the well-known "Domain Users" group?
Or what if some users' primary group was changed to "CN=rebels,DC=mycompany,DC=com", and I wanted to get members of THAT group? Users don't have a memberOf property for their primary group, and the primary group won't have a member property listing them.
This is what I see when viewed via LDAP (ie, no MS extensions):
To get the the primaryGroupToken from any given group extract it from the objectSid so for example Domain Users objectSid = S-1-5-21-704657944-2065781323-617630493-513 then the primaryGroupToken is the last digits after the "-" so in the case of the "Domain Users" its 513
You need to find out primaryGroupToken from the Group object first. If you are using ADSIEdit, you need to make sure you have "Constructed" filter on to see this calculated attribute. For Domain Users, the primaryGroupToken should be 513.
Then, you neeed to find all the users with primaryGroupID set to this value. Here is the ldap query you should write to find out all users with Domain Users set as the primary group.
(&(objectCategory=person)(objectClass=user)(primaryGroupID=513))
EDIT
Here is the steps to show primaryGroupToken in LDAP Browser. I am using LDAP browser 2.6 build 650. Right click your profile and click properties
Go to LDAP Settings tab and click Advanced button.
Add an extra operational attribute primaryGroupToken
Click Apply button and close the properties page. Now, you should see the primaryGroupToken in your group object.
This is a PS script that I made to do exactly that:
[void][System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices");
$groupName = "Grupo Domain";
$directoryEntry = New-Object System.DirectoryServices.DirectoryEntry;
$directorySearcher = New-Object System.DirectoryServices.DirectorySearcher($directoryEntry, "(&(objectClass=group)(CN=$groupName))");
[void]$directorySearcher.PropertiesToLoad.Add("objectSid");
[void]$directorySearcher.PropertiesToLoad.Add("member");
$result = $directorySearcher.FindOne();
if ($result -eq $null) { return; }
# Try get the group members through the "member" property.
if ($result.Properties["member"].Count -gt 0) {
foreach ($member in $result.Properties["member"]) {
$memberSearcher = New-Object System.DirectoryServices.DirectorySearcher($directoryEntry, "(&(objectClass=*)(distinguishedName=$member))");
[void]$memberSearcher.PropertiesToLoad.Add("msDS-PrincipalName");
$memberResult = $memberSearcher.FindOne();
if ($memberResult -eq $null) { continue; }
Write-Output $memberResult.Properties["msDS-PrincipalName"];
}
return;
}
if ($result.Properties["objectSid"].Count -gt 0) {
# The group might be an AD primary group. Try get the members by the PrimaryGroupID.
$groupSid = New-Object System.Security.Principal.SecurityIdentifier($result.Properties["objectSid"][0], 0);
# Hacky way to get only the last RID.
$primaryGroupSid = $groupSid.Value.Replace($groupSid.AccountDomainSid.ToString(), [String]::Empty).TrimStart('-');
$memberSearcher = New-Object System.DirectoryServices.DirectorySearcher($directoryEntry, "(&(objectClass=*)(primaryGroupId=$primaryGroupSid))");
[void]$memberSearcher.PropertiesToLoad.Add("msDS-PrincipalName");
$memberResult = $memberSearcher.FindAll();
if ($memberResult -eq $null) { continue; }
foreach ($member in $memberResult) {
Write-Output $member.Properties["msDS-PrincipalName"];
}
}

Resources