Using a global catalog in PowerShell - powershell

I have multiple domains in my forest, and I'm trying to write a script that will work with any user in the forest, so I'm using a global catalog in my script.
This works to retrieve the data, but when I try and modify the data I'm getting
Set-ADUser : The server is unwilling to process the request
If I use the domain controller (DC) as the server name, the modification completes as it should. I'd like to avoid writing a switch to set the server name. Is there anything else I can do here?
Get-ADUser $user -Server "contoso.local:3268" | %{Set-ADUser -Identity $_.distinguishedname -SamAccountName $_.SamAccountName -Server "contoso.local:3268"}

I'm not really clear on what you're trying to do here. Global catalog ports are read only (for LDAP).
If you want to make sure you find a domain controller that is a global catalog, you can use the following:
Get-ADDomainController -Discover -Service GlobalCatalog
Based on your comment, maybe what you need is $PSDefaultParameterValues:
$PSDefaultParameterValues = #{
"*-AD*:Server" = "contoso.local:3268"
}
Get-ADUser $user |
%{Set-ADUser -Identity $_.distinguishedname -SamAccountName $_.SamAccountName }

Related

How to run this script against another domain

I have the script below to give me the distinguished name for groups in a spreadsheet I have. The issue is, the groups are located in another domain. How do I point my script to that domain? Issue is I know I have to be logged in to that domain to run it but I cant.
$Groups = Get-Content -Path C:\Scripts\DistinguishedName.csv
ForEach ($Group in $Groups) {
Get-ADGroup -Identity $Group | Select-Object distinguishedName
}
The cmdlets in the Active Directory module support passing in the value of the domain controller you are wanting to query. By default when you call Get-ADGroup (or any of the other) it will validate what domain it should query by checking the domain of your current machine.
The other option is to provide the -Server (doc) with the value of the Active Directory Domain Services you want to execute your query against.
You can also provide the -Credential parameter with a PSCredential object that contains your login for that other domain. This is required if the current login of your PowerShell session is not authorized to authenticate against that other domain.
So your example script would look something like this:
$AdDomain = "whatever.company.local"
$adCred = Get-Credential
$Groups = Get-Content -Path C:\Scripts\DistinguishedName.csv
ForEach ($Group in $Groups) {
Get-ADGroup -Identity $Group -Server $AdDomain -Credential $adCred | Select-Object distinguishedName
}

Processing ForeignSecurityPrincipal

DomainA and DomainB trust each other. Some DomainB users are members of DomainA local domain groups. How can I get ForeignSecurityPrincipal in PowerShell and get list of its groups?
That was surprisingly simple:
Get-ADObject -Filter {ObjectClass -eq "foreignSecurityPrincipal"} -Properties msds-principalname,memberof
where "msds-principalname" is sAMAccountName, so I can search now through FSPs by sAMAccountName and get its groups.
You can get the list of foreign security principals in a domain by running Get-ADObject cmdlet with SearchBase set to CN=ForeignSecurityPrincipals,DC=domain,DC=com and LDAPFilter to something acceptable, like (|(objectCategory=user)(objectCategory=group)). Then, you can use this script to get its domain\username. Then you query that domain for DCs via Get-ADDomain and Get-ADDomainController, get the user object from there and run Get-ADPrincipalGroupMembership in your current domain against the retrieved user. An example (untested, as I have no env with many domains):
$ldf='(|(objectCategory=user)(objectCategory=group))'
$fspc=(get-addomain).ForeignSecurityPrincipalsContainer
$fsps = get-adobject -ldapfilter $ldf -searchbase $fspc
# got principals here
foreach ($fsp in $fsps) {
$fspsid=New-Object System.Security.Principal.SecurityIdentifier($fsp.cn)
($fspdomain, $fspsam) = ($securityPrincipalObject.Translate([System.Security.Principal.NTAccount]).value).Split("\")
# ^ this can throw exceptions if there's no remote user, take care
$fspdc=(get-addomaincontroller -domainname $fspdomain -discover)[0] # taking first one
$fspuser=get-aduser $fspsam -server $fspdc.hostname # use crossdomain DNS to resolve the DC
$fspgroups=get-adprincipalgroupmembership $fspuser # local query
$fspgroups # now do whatever you need with them and the $fspuser
}

Using a different active directory tree in powershell

So I have a script with the purpose of scanning devices that start with a certain name, then return results of computers missing a group. My problem is, the device I need it to run from turns out not to be in the same tree. I have seen some commands, but I wanted to be sure I had the syntax right. I will include part of the script for context:
Import-Module ActiveDirectory
$Group = "A-Certain-Group"
$Groupname = (Get-ADGroup $Group).distinguishedName
$Computers = Get-ADComputer -filter "name -like 'Big*'" -Prop MemberOf | Where{$_.MemberOf -notcontains $Groupname}
So let's say I am running it from "company.net", and it needs to perform the above script on "companynet.net" instead. What is the proper method?
The AD cmdlets all have a -server parameter which lets you specify other domains. Just use it to specify the other domain assuming there is a trust.
$Groupname = (Get-ADGroup $Group -Server companynet.net).distinguishedName
$Computers = Get-ADComputer -Server companynet.net -filter "name -like 'Big*'" -Prop MemberOf | Where{$_.MemberOf -notcontains $Groupname}
Note that if you don't have permission to perform actions in the domain you will also need to use the -credential parameter.

get all ADcontroller of another domain

I'm stuck in a stupid problem that I can't figure out how to solve.
I need to get all domain controllers of a trusted domain.
With this piece of code I get all DC in the current domain Get-ADDomainController -Filter *
With this I get one DC from target domain Get-ADDomainController -domain MyTrustedDomain -Discover
But how can I get all DC in target domain?
Can't test this due to lack of AD, but you could try the -Server option with the FQDN of the trusted domain:
Get-ADDomainController -Filter * -Server trusted.example.com
One way without using AD module:
$a = new-object 'System.DirectoryServices.ActiveDirectory.DirectoryContext'("domain", "other.domain.local" )
[System.DirectoryServices.ActiveDirectory.DomainController]::FindAll($a)
You need to be an 'authenticated user' in the remote domain or add username and password parameter to the DirectoryContext object
This command will list all domain controllers in the forest for each domain
(get-adforest).domains |%{get-addomaincontrollers -filter * -server $_}
I've come across the same problem as I work regularly with multiple domains. I was hoping for a more elegant solution, but so far the best I've come up with is to take your work one step further.
if Get-ADDomainController -domain MyTrustedDomain -Discover gives you one server in the target domain, you can feed that to the -server parameter to query that one DC. You do need to provide credentials to query a DC from a different domain than your login session if a trust DOES NOT exist (in a trust, the trusting domain considers you to be 'authenticated').
$targetdcname = (Get-ADDomainController -DomainName <MyTrustedDomain> -Discover).hostname
Get-ADDomainController -Filter * `
-Server $targetdcname `
-Credential (Get-Credential MyTrustedDomain\username) | ft HostName
or
Get-ADDomainController -Filter * `
-Server $((Get-ADDomainController -DomainName <MyTrustedDomain> -Discover).hostname) `
-Credential (Get-Credential MyTrustedDomain\username) | ft HostName
If you do this sort of thing alot, you can always store your credentials in a variable for reuse, $cred = Get-Credential MyTrustedDomain\username) and save the repeated prompts. The password is stored as a System.Security.SecureString and will be secure as long as you keep it within your session.
Until the Get-ADDomainController cmdlet is updated to allow both the -filter parameter AND the Domainname parameter, we're stuck with a workaround.
from: help get-addomaincontroller -examples
This should list all DCs in your domain
-------------------------- EXAMPLE 12 --------------------------
C:\PS>Get-ADDomainController -Filter { isGlobalCatalog -eq $true -and Site -eq "Default-First-Site-Name" }
Get all global catalogs in a given site.
Get-ADDomain -Identity <DOMAIN NAME> | select -ExpandProperty ReplicaDirectoryServers
Here is what I used
cls
$domains = (Get-ADForest).Domains;
foreach ($domain in $domains)
{
Write-Host $domain
(Get-ADDomain -Identity $domain | select -ExpandProperty ReplicaDirectoryServers).Count;
Write-Host "";
$totalCount = $totalCount + (Get-ADDomain -Identity $domain | select -ExpandProperty ReplicaDirectoryServers).Count;
}
Write-Host "Total domain controller count is: "$totalCount
Thanks for the start, here's what I came up with. Then I feed it to a SharePoint list.
get-adtrust -Filter * | Select-object Name, Domain,ipv4Address, OperatingSystem, Site, HostName, OperatingSystemVersion | ForEach-Object{Get-ADDomainController -Filter * -Server $_.Name}
Sometimes Powershell adds complexity, just open a cmd prompt and enter
C:\Windows\System32\nltest.exe /dclist:[trusted domain]
Of course, replace [trusted domain] with the name of the domain whose DC's you want.

PowerShell Add 1 day to the AccountExpire attribute of an AD user

As topic states. How can I put 1 extra day to the selected user account.
I know AD goes by Windows File Time. Does anyone know the easiest and least code written method?
You can modify the accountExpires property of an AD user through the Set-ADUser cmdlet included in Windows Server 2008 R2:
Import-Module activedirectory
$expireDate = (Get-ADUser -Identity "John Appleseed" -Properties accountExpires).accountExpires
$renewedExpireDate = ([System.DateTime]::FromFileTime($expireDate)).AddDays(1)
Set-ADUser -Identity "John Appleseed" -AccountExpirationDate $renewedExpireDate
As you said, the value of the accountExpires property is represented as a Windows file time, which is a 64-bit integer. In this example we convert it to a DateTime to easily modify it and then pass it to the -AccountExpirationDate parameter to update the user.
Using Quest AD module:
Set-qaduser <username> -AccountExpires ( [datetime]( get-qaduser <username> -IncludeAllProperties ).AccountExpires ).AddDays(1)
This can also be accomplished in a multi domain environment by adding the -server switch and passing in the domain string (i.e. "domain.corp.root"). I also had to move the .accountExpires as it was in the wrong place in this code sample. Thanks for providing this, it was exactly what I needed.
Import-Module ActiveDirectory
$expireDate = (Get-ADUser -Identity "samaccountname" -Properties accountExpires -server "domain.corp.root")
$renewedExpireDate = ([System.DateTime]::FromFileTime($expireDate.accountExpires)).AddDays(1)
Set-ADUser -Identity "samaccountname" -AccountExpirationDate $renewedExpireDate -server "domain.corp.root"