Powershell connecting and searching multiple domains - powershell

I am trying to locate the group memberships for a specified user account. One domain's user account is often a member of a group in the other domains (some domains require different admin account). Using get-QAQgroup, I can successfully search each domain individually, but when I try to loop through the domains, I can only find results in the domain that I am logged into.
#Script to change domains and look for group memberships for a specified user account.
$domains = "dom1.ad.state.company.com","dom2.ad.state.company.com","dom3.ad.state.company.com","dom4.ad.state.company.com","corporate.state.company.com","OddNamedDom.com"
$CRED=GET-CREDENTIAL
$userAcc = read-host "Enter domain\username for Group Membership Search"
foreach ($domain in $domains)
{
write-host "In the domain $domain "," $userAcc is a direct member of..."
Get-QADGroup -service $domain -Credential $cred -Containsmember $userAcc | select name
} #foreach domain
Connect-QADService -Service 'dom1.ad.state.company.com'
When I run the script I get results for dom1 (domain I am logged into) and the rest throw the following errors. I am not sure why the "Ref 1:.." lines are pointing to 'dom1'. I thought that might be the source of issue. I have copied the Powershell output below showing the error messages.
In the domain dom1.ad.state.company.com dom1\brownd2.admin.dom1 is a direct member of...
Name
----
DOM1-G-ITS-DS-Company Services
DOM1PGUELFP00003-Exmerge-R
DOMPGUELFP00003-Exmerge-C
ITSPPTBOSHFS003-FSSHARE-C
Domain Users
In the domain dom2.ad.state.company.com dom1\brownd2.admin.dom1 is a direct member of...
Get-QADGroup : 0000202B: RefErr: DSID-03100742, data 0, 1 access points
ref 1: 'dom1.ad.state.company.com'
At C:\TestScripts\tGet-UserAllMemberships.ps1:24 char:6
+ Get-QADGroup -service $domain -Credential $cred -Containsmember $userAcc | ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-QADGroup], DirectoryAccessException
+ FullyQualifiedErrorId : Quest.ActiveRoles.ArsPowerShellSnapIn.DirectoryAccess.DirectoryAccessException,Quest.ActiveRoles.ArsPowerShel
lSnapIn.Powershell.Cmdlets.GetGroupCmdlet
In the domain dom3.ad.state.company.com dom1\brownd2.admin.dom1 is a direct member of...
Get-QADGroup : 0000202B: RefErr: DSID-03100742, data 0, 1 access points
ref 1: 'dom1.ad.state.company.com'
At C:\TestScripts\tGet-UserAllMemberships.ps1:24 char:6
+ Get-QADGroup -service $domain -Credential $cred -Containsmember $userAcc | ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-QADGroup], DirectoryAccessException
+ FullyQualifiedErrorId : Quest.ActiveRoles.ArsPowerShellSnapIn.DirectoryAccess.DirectoryAccessException,Quest.ActiveRoles.ArsPowerShel
lSnapIn.Powershell.Cmdlets.GetGroupCmdlet
There is a similar set of errors for each domain that I am checking. I have not posted the full list of error messages.
If I change the order of the domains in the array, the errors and the results of the one successful domain just change order to match the array. I thought that it might just be successful for the first iteration of the loop. Not the case though.
I know that the account is a member of groups in Dom2 and not in any groups in Dom3. If I take the commands out of the foreach loop and run individual for each domain in the console I do get the expected results. Based on the individual results, I had thought that this would be straight forward example to do in a loop, but I am not connecting correctly to the domains.
What can I change?

Here is a solution using System.DirectoryServices.AccountManagement Namespace, adapted to PowerShell from C# code. It's a kind of recursive solution. In Find Recursive Group Membership (Active Directory) using C#, I give a recursive solution (using basic ADSI avaible from PowerShell 1.0) that also works with distribution groups.
# Retreiving a principal context for the administrator on the Global Catalog
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$domainContext = New-Object DirectoryServices.AccountManagement.PrincipalContext([DirectoryServices.AccountManagement.ContextType]::Domain, "VMESS01:3268" , "administrator", "adminPasswd")
# Retreive the groups
try {
$userPrincipal = [DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($domainContext, "jpb")
$groups = $userPrincipal.GetAuthorizationGroups()
foreach($group in $groups)
{
$group.name;
}
}
finally {
$pc.domainContext()
}

Related

Cannot convert System Object to String Powershell

Hi I am trying to use the below powershell script
$get_AD_Server = (Get-WmiObject -Class Win32_NetworkAdapterConfiguration).DnsDomain | Out-String
$get_Nearest_DC = (Get-ADDomainController -DomainName $get_AD_Server -Discover -NextClosestSite).Name
The output of $get_AD_Server contains contoso.com, however when i pass the variable $get_AD_Server in the next variable it always errors out, any idea on what am i doing wrong?
Get-ADDomainController : The format of the specified domain name is invalid
At line:2 char:20
+ ... arest_DC = (Get-ADDomainController -DomainName $get_AD_Server.ToStrin ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (:) [Get-ADDomainController], ADException
+ FullyQualifiedErrorId : GetADDomainController:BeginProcessingOverride:DiscoverDC:1212,Microsoft.ActiveDirectory.Management.Commands.GetADDomainController
Automatic variable unrolling will return a collection.
DNSDomain property may not be populated. In my case it isn't. Assuming you've got that covered I think you might have better luck if you isolate the NIC configuration you care about. If you narrow the return to 1 object .DNSDomain will be a string.
In my case this looks like:
(Get-WmiObject win32_NetworkAdapterCOnfiguration -Filter "IPEnabled = 'True'").DnsDomain
If needed just work on the filter until you find something that reliably only returns the NIC you care about.
Note: I may have misread something, but I worry you'll have an issue with the next step. You may have trouble querying the AD domain when you aren't authenticated. If you do hit something like that you may consider using the -Credential parameter on Get-ADDomainController. Of course it'd be interactive at that point.
Instead of fetching the DNS domain associated with the NIC, pull the computers domain from the Win32_ComputerSystem class:
$domain = (Get-WmiObject -Class Win32_ComputerSystem).Domain
$nearestDC = (Get-ADDomainController -DomainName $domain -Discover -NextClosestSite).Name

String variable in an Active Directory path not working

I'm writing a PowerShell script to create a new Active Directory group and automatically put it in the correct OU, depending on what department the user is in. The script gets the department from the user in Active Directory and then needs to use that as the name of the OU in active directory. When I don't use the variable in the AD path, this script works.
[string]$department = Get-ADUser -identity johndoe -properties department | Select department
New-ADGroup -Name NewADGroup -GroupScope Global -path “OU=($department),OU=SubDepartment,OU=MainDepartment,DC=OrgName”
However, when I try to use the variable $department as above, I get the following error:
New-ADGroup : The object name has bad syntax
At C:\Users\JohnDoe\Desktop\CreateNewGroup.ps1:7 char:1
+ New-ADGroup -Name NewADGroup -GroupScope Global -path
"OU=($department ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (CN=NewADGroup,DC=OrgName
:String) [New-ADGroup], ADException
+ FullyQualifiedErrorId : ActiveDirectoryServer:8335,Microsoft.ActiveDirec
tory.Management.Commands.NewADGroup
How can I call that variable inside the Active Directory path?
You actually have 2 issues here that are common pitfalls.
$department is not a string per se but a string representation of an object with a deparment property. You need to break the string out. That is what -ExpandProperty was for. If you looked at your department now you would see something like #{Department="IT"}
You are also having issues with variable expansion in strings.
[string]$department = Get-ADUser -identity johndoe -properties department | Select -Expandproperty department
New-ADGroup -Name NewADGroup -GroupScope Global -path "OU=$department,OU=SubDepartment,OU=MainDepartment,DC=OrgName"
If you are not calling properties or complex object then removing the brackets is sufficient. Else you can just use a sub expression "OU=$($department),OU=SubDepartment,OU=MainDepartment,DC=OrgName". Without the $ sign the brackets were considered part of the string.
try a dollar sign in front of the opening parenthesis like this:
"OU=$($department)..."

Adding members to local groups by SID in multiple languages

I'm new to powershell/scripting/life in general, but finally I got a problem that is worthy of asking for help:
I've various Windows localizations in environment - English, Finnish and Russian in current environment, but with possibilities to have other Scandinavian/European localizations. I need to add Authenticated users to Administrators group. I can script it in English:
NET LOCALGROUP Administrators "Authenticated Users" /add,
but I won't know all localized names. For example, in Russian it would be "Administratori" and "Proshedshie Proverku." In cyrilic, that I'm not that strong with anyway.
Of course, I know SIDs - S-1-5-32-544 for Administrators and S-1-5-11 for Authenticated users. However, running
NET LOCALGROUP S-1-5-32-544 S-1-5-11 /add returns error that group doesn't exist. Ok, so I found a script to check it -
$objUser = New-Object System.Security.Principal.NTAccount("kenmyer")
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
$strSID.Value
This returns expected value, so far so good. Then I tried to double check it -by running line to get name from SID -
$Admin = (Get-WMIObject -Class Win32_Group -Filter "LocalAccount=True and SID='S-1-5-32-544'").Name
$Auth = (Get-WMIObject -Class Win32_Group -Filter "LocalAccount=True and SID='S-1-5-11'").Name
And $Admin = Administratori (as it should be), while $Auth = nothing. There is no name. And that's where I stopped. I tried this in English environment as well - still got "no such group" message. Running first command I wrote, with both names in English - Works perfectly Ok.
Any ideas?
Upd:
Perhaps I can't explain properly what I'm trying to do, so let the script do the talking:
#Task: to add "Authenticated users" to "Administrators" group in any languange OS.
$objSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544")
$objgroup = $objSID.Translate( [System.Security.Principal.NTAccount])
$objgroupnameAdm = ($objgroup.Value).Split("\")[1]
$objSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-11")
$objgroup = $objSID.Translate( [System.Security.Principal.NTAccount])
$objgroupnameAuth = ($objgroup.Value).Split("\")[1]
#Administratörer
#Autentiserade användare
net localgroup $objgroupnameAdm $objgroupnameAuth /add
I try this on Swedish Win7 right now. So result is:
net.exe : Syntaxen för kommandot är:
At line:13 char:4
+ net <<<< localgroup $objgroupnameAdm $objgroupnameAuth /add
+ CategoryInfo : NotSpecified: (Syntaxen för kommandot är::String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
I've tried also putting $objgroupnameAuth in quotes, as it contains two words, but that gives same result. Definig variables as string - no changes, and replacing $objGroupNameAdm with actual value - no changes.
If I couldn't do it in English Windows, I would assume that it's just functionally impossible.
I use this method to translate from SID to localized name:
.SYNOPSIS
Adds the "NT AUTHORITY\Interactive security principal to the local computer Administrators group"
.DESCRIPTION
THis script uses a SID translation to receive the localized name for the Interactive principal and the Administrators group, then adds the principal to the group using the localized names.
# Translate the S-1-5-32-544 (.\Administrators) SID to a group name, the name varies depending on the language version of Windows.
$sid2 = 'S-1-5-32-544'
$objSID2 = New-Object System.Security.Principal.SecurityIdentifier($sid2)
$localadminsgroup = (( $objSID2.Translate([System.Security.Principal.NTAccount]) ).Value).Split("\")[1]
# Translate the S-1-5-4 (NT AUTHORITY\Interactive) SID to an account name, the name varies depending on the language version of Windows.
$sid1 = 'S-1-5-4'
$objSID1 = New-Object System.Security.Principal.SecurityIdentifier($sid1)
$interactive = (( $objSID1.Translate([System.Security.Principal.NTAccount]) ).Value).Split("\")[1]
# Add the security principal name to the local administrators group. (used old style of adding group members due to compatibility reasons)
try {
Write-Host "Adding security principal: $interactive to the $localadminsgroup group..."
$group = [ADSI]"WinNT://$env:computername/$localadminsgroup,group"
$ismember = "False"
#($group.Invoke("Members")) | ForEach-Object {
If ($interactive -match $_.GetType.Invoke().InvokeMember("Name", 'GetProperty', $null, $_, $null)) {
$ismember = "True"
}
}
If ($ismember -eq "True") {
write-host "user $interactive is already a member of $localadminsgroup"
}
Else {
$result = $group.Add("WinNT://NT AUTHORITY/$interactive,user")
write-host "user $interactive is added to $localadminsgroup"
}
}
Catch {
write-host $_.Exception.Message
}
It's not entirely tailored towards what you need but I'm sure you can make it work.
Regards,
Koen.
The SID S-1-5-11 is used for Authenticated Users (Well known SIDs). That is a BUILTIN group that cannot be modified. Other groups like this are Everyone, or Anonymous, etc.
This type of group doesn't exist in the "physical" sense or the word, i.e. there is no object created either in the local SAM nor in the Active Directory.
They are entirely generated and managed by Windows.
You receive the SID in your session depending on how you connected and/or logged on.
Therefore making a WMI Win32_Group request, or using Get-ADGroup won't return anything.
You can invoke Get-ADAccountAuthorizationGroup, to see if a particular identity is member of such groups.
You can use the SID to retrieve create a create a System.Security.Principal.NTAccount object pointing to Authenticated Users:
$auth = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-11")
$name = $auth.Translate([System.Security.Principal.NTAccount])
UPDATE:
I could not add the localized name of $auth to that group. Looks like only the English version works.
Question is simple, once asked correctly, and answer is to be found here: Microsoft Supprt: NET /ADD command .
If NET limit is 20 characters, and "Autentiserade användare" is 24 characters, it's not supposed to work. Workaround is to be found in the same link.

How to return the users in a domain local group in Powershell

When I run the following command on a domain local group:
Get-ADGroupMember "Name of Group"
I get the following output:
Get-ADGroupMember : The operation completed successfully
At line:1 char:1
+ Get-ADGroupMember "Name of Group"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (Name of Group:ADGroup) [Get-ADGroupMember], ADException
+ FullyQualifiedErrorId : The operation completed successfully,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember
When I run the command on a global group, I get the output of the users in the group. Is there a way to get the users from a domain local group?
If this doesn't work:
Get-ADGroup "Name of Group" | Get-ADGroupMember
Try the following:
$s = "LDAP://" + (Get-ADGroup "Name of Group").DistinguishedName
([ADSI]$s).member
if you want to export the users from a domain local group use this code:
$s = "LDAP://" + (Get-ADGroup "Name of Group").DistinguishedName
([ADSI]$s) | select -ExpandProperty member| select #{Name=’members‘;Expression={[string]::join(“;”, ($_))}} | export-csv C:\Path\File.csv -NoTypeInformation
Warning: if you have users from another domain in the domain local group they will appear as SIDs.
I ran into this error when looking at distribution groups. - I got no error, but the 4 members of the group were not listed. I was convinced it was because it was a domain local group.
I had set the recipient scope to the entire forest (Set-AdServerSettings -ViewEntireForest $true). For whatever reason, if you do that, you should use the DN (rather than alias or name) to get the members, and also include the switch -ReadFromDomainController. So, I had to use
Get-DistributionGroupMember -Identity DistinguishedName -ReadFromDomainController

Powershell: How to pass variable correctly to command

I apologize if I butchered the terminology for this, and understand I'm very new to PowerShell. I have read over some of the guides and this concept is clearly not getting through to me.
Concept:
I want to remove a mobile device from a user in Exchange 2010
Identify user from input
Create variable from input of the PhoneID
Remove the Phone using phoneID variable
I believe my problem is in how I'm passing this data to the next command. I know the appended "#[Identity " that get's added should be removed and I remember reading something about how when you pass data like this Powershell has no context? Here is my very simple script.
Script
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
. $env:ExchangeInstallPath\bin\RemoteExchange.ps1
Connect-ExchangeServer -auto
$PU = Read-Host "Enter Username"
$did = get-activesyncdevice -mailbox $PU | Select-Object identity
Remove-ActiveSyncDevice -Identity $did
Error
My error is as follows, and I've tried to research what I'm doing wrong but I'm just not getting it :-( , I replaced the actual output for the account with XX.
Remove-ActiveSyncDevice : Cannot bind parameter 'Identity'. Cannot convert value "#{Identity=XX" to type
"Microsoft.Exchange.Configuration.Tasks.ActiveSyncDeviceIdParameter". Error: "Cannot convert the "#{Identity=XX}" value of type
"Selected.Microsoft.Exchange.Data.Directory.SystemConfiguration.ActiveSyncDevice" to type "Microsoft.Exchange.Configuration.Tasks.ActiveSyncDeviceIdParameter"."
At line:1 char:35
+ Remove-ActiveSyncDevice -Identity $did
+ ~~~~
+ CategoryInfo : InvalidArgument: (:) [Remove-ActiveSyncDevice], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.Exchange.Management.Tasks.RemoveMobileDevice
Any help or advice on this would be amazing!
When you use Select-Object and give it just one property name, you get and object with just one property. But even though it only has one property, you still have to reference that one property by name:
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
. $env:ExchangeInstallPath\bin\RemoteExchange.ps1
Connect-ExchangeServer -auto
$PU = Read-Host "Enter Username"
$did = get-activesyncdevice -mailbox $PU | Select-Object identity
Remove-ActiveSyncDevice -Identity $did.identity