Powershell Get Distinguished Name of Exchange Server - powershell

I'm searching to gather the Distinguished name of an exchange server to show it's version.
Here's the code I already have, in which is missing the automated function allowing to gather the DN, also, I'm loading the script from my active directory:
$Dinstinguishedname = Read-Host -Prompt 'Input Distinguished Name of your exchange server (e.g. :CN=Servers,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups,CN=Exchange-Domain-Enzo,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=domain,DC=eu)'
$conteneur=get-adobject "$Dinstinguishedname"
cd AD:\$conteneur
$a=get-childitem
foreach ($i in $a){ get-adobject $i -Properties serialnumber}
Remove-Variable -Name conteneur,a,i
cd C:
Write-Host "variable cache cleared :p" -fore Red
#CN=Servers,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups,CN=Exchange-Domain-Enzo,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=domain,DC=eu

Related

Moving user in Active Directory using PowerShell won't work

I am trying to make a script that allows new users on the domain to be put into certain groups based on their tag e.g [DALT]. When I run the script it should work properly as it uses the correct OUs and target path but it seems to not work the way I expect it to. I use a credential saved on my D drive as the cred to have admin rights.
$deviceName = Hostname
$deviceName = $deviceName -replace '[^a-zA-Z]', ''
$defaultName = Hostname
# Import Cred for access to change Dir
$credential = Import-Clixml -Path 'D:\backgroundProcess\cred.xml'
$credential
# Directing users to different part of AD depending on deviceName
# Action House (Branch of Company)
if ($deviceName -eq 'DALT') {
Move-ADObject -Identity "CN=$defaultName,CN=Computers,DC=internal,DC=ttlhidden,DC=co,DC=uk" -TargetPath "OU=Windows,OU=Laptop,OU=Computers,OU=DEKRA,DC=internal,DC=ttlhidden,DC=co,DC=uk"
Write-Host "$defaultName added to Hidden group."
gpupdate /force
}
else {
Write-Host "Sorry, $deviceName is not a verified name, please contact Max for more information."
}
Remove-Item -Path 'cred.xml'
It always seems to render the else option even if my computer has DALT at the start.

Powershell GPO Login Script checking AD resource group membership

The system I have to work with uses AD resource group membership to manage most of the permissions for users and computers. I have been asked to improve the current logon script as it currently contains some VB ADSISEARCHER calls. I started trying to do this purely in powershell but have hit a number of hurdles.
Target machines do not have the Active Directory Module installed
The users logging into the system have a restricted user accounts
The resource groups are nested so the script needs to handle this
I have tried a couple of approaches firstly the pure Powershell Cmdlet method of Get-ADGroup or Get-ADPricipalGroupMembership but these Cmdlet's require the Active Directory Module. Then I tried the .net approach with System.DirectoryServices.DirectoryEntry although this is a step away from a pure PowerShell solution at least it isn't as Legacy as the VB route. However when I try to build the object it also appears to be missing the name space.
First Attempt:
function Get-UserResourceMembership
{
[CmdletBinding()]
Param
(
# Username or Groupname to Discover Group Membership
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
$User
)
Begin
{
$Groups = #(Get-ADPrincipalGroupMembership $User)
}
Process
{
foreach($ADGroup in $Groups)
{
if($ADGroup.ObjectClass -eq "Group")
{
Get-UserResourceMembership $ADGroup
}
$GrpMembership = #($ADGroup)
}
}
End
{
return ,$GrpMembership
}
}
Second Attempt:
# $rootGroup is passed in from earlier in the script
$groupname = $rootGroup.'Group Name'
$filter = ("(&(objectCategory=Group)(name=$($groupname)))")
$searcher.Filter = $filter
$searcher.SearchScope = "Subtree"
$searchResults = $searcher.FindAll().GetDirectoryEntry().memberOf |
% { (New-Object System.DirectoryServices.DirectoryEntry("LDAP://"+$_)) } |
Sort-Object Children | select #{name="Group Name";expression={$_.Name}}
foreach($resource in $searchResults)
{
if($resource.'Group Name' -match "<Groupname>")
{
$printResource += $resource
}
}
Does anyone in the community have any suggestions how to pull group membership [nested] from Active Directory from a standard users login script??? Any idea's much appreciated....
PS I can't change the way the system is designed (above my pay grade).
As for ...
• Target machines do not have the Active Directory Module installed
• The users logging into the system have a restricted user accounts
• The resource groups are nested so the script needs to handle this
Does not matter, they do not need to be installed on a client to use
them. You can use PSRemoting to proxy those using 'Implicit
Remoting'. The cmdlets are only available in the remote session.
Does not matter, as every user has read access, by default to ADDS
in Windows.
You can get to those using the cmdlets you are using and
there are even pre-built scripts in the Microsoft PowershellGallery.com
for this as well.
As for …
I have tried a couple of approaches firstly the pure Powershell Cmdlet
method of Get-ADGroup or Get-ADPricipalGroupMembership but these
Cmdlet's require the Active Directory Module.
As noted above, this can be addressed as described below:
PowerShell Implicit Remoting: Never Install a Module Again
Remote Session
# create a session then import a module via the session, for example:
$adsess = New-PSSession -ComputerName savdaldc01
Import-Module -Name ActiveDirectory -PSSession $adsess
Get-Module
Get-ADUser -Filter *
Remove-Module ActiveDirectory
# It's also possible to prefix modules loaded from remote servers to differentiate from local modules, e.g.
Import-Module -Name ActiveDirectory -PSSession $adsess -Prefix OnDC
Get-OnDCADUser -Filter * #I don't have regular Get-ADUser anymore
Remove-Module ActiveDirectory
Remove-PSSession $adsess
As for ...
Does anyone in the community have any suggestions how to pull group
membership [nested]
Get nested group membership - function
This function will recursively enumerate members of a given group
along with nesting level and parent group information. If there is a
circular membership, it will be displayed in Comment column.It accepts
input from pipeline and works well with get-adgroup. Download:
Get-ADNestedGroupMembers.ps1
As well as just doing this...
We can get group members by using the Active Directory powershell
cmlet Get-ADGroupMember. The Get-ADGroupMember cmdlet provides the
option to get all the nested group members by passing the parameter
-Recursive. This powershell script also handles circular membership (infinite loop) problem.
Function Get-ADNestedGroupMembers
{
[cmdletbinding()]
param
(
[String] $Group
)
Import-Module ActiveDirectory
($Members = Get-ADGroupMember -Identity $Group -Recursive)
}
Get-ADNestedGroupMembers "Domain Admins" | Select Name,DistinguishedName
or this way.
function Get-NestedGroupMember
{
param
(
[Parameter(Mandatory, ValueFromPipeline)]
[string]$Identity
)
process
{
Import-Module ActiveDirectory
$user = Get-ADUser -Identity $Identity
$userdn = $user.DistinguishedName
$strFilter = "(member:1.2.840.113556.1.4.1941:=$userdn)"
Get-ADGroup -LDAPFilter $strFilter -ResultPageSize 1000
}
}
All of the methods below list all groups including nested groups.
The example below would execute a gpresult command in the user's context. The gpresult outputs to an XML file within the user's local profile, which they should have full access to already. Then the XML file is read and traversed through each node until you reach the node containing the groups. The group list contains local and domain groups and is outputted directly to the console. This can easily be stored in a variable or output to a file. If you only want domain groups, that could easily be filtered from here with a Regex. It requires that the client machines are running at least Windows Vista SP1 or later.
gpresult /USER "$env:userdomain\$env:username" /X "$env:userprofile\rsop.xml"
$xml = [xml](Get-Content "$env:userprofile\rsop.xml")
$xml.Rsop.UserResults.SecurityGroup.Name."#text" # Displays the groups
Remove-Item "$env:userprofile\rsop.xml" # Removes the XML file
You could also use a potentially use Regex matching to find the group list:
$out = gpresult /R /USER $env:username
$GroupsUnfiltered = (($out | out-string) -split "-{10,}")[-1]
$Groups = ($GroupsUnfiltered.trim() -replace "(?m)^\s+","") -split "(?m)\r?\n"
$Groups
The following can also work if your group list always begins with a predictable group like Domain Users in this example:
$out = gpresult /R /USER $env:username
$GroupList = $out.where({$_ -match "domain users"},'SkipUntil').trim()
$GroupList
This code assumes that the users and machines are joined to the same domain or are at least joined to trusted domains. The second code snippet assumes every user is in the Domain Users group and the machines are natively PowerShell v4 or higher.

Powershell Deployed via SCCM Issue

I am writing a powershell script to be deployed by SCCM via a package. The aim of this is to remove an account with a specific name then write to a file stating if the account exists or not. The code is below:
$Computer = hostname
foreach ($C in $Computer) {
if (Test-Connection $C -Quiet) {
Write-Verbose "$C > Online"
$Users = Get-WMIObject Win32_UserAccount -Filter "LocalAccount=True" -ComputerName $C
if ($Users.Name -contains 'test') {
Add-Content \\SERVERNAME\SHARENAME.$\$computer-found_$(get-date -Format yyyymmdd_hhmmtt).txt "User 'test' found, Disable 'test' found"
net user test /active:no }
else {
Add-Content \\SERVERNAME\SHARENAME.$\$computer-notfound_$(get-date -Format yyyymmdd_hhmmtt).txt "User 'test' not found"
}
}
else {
Write-Verbose "$C > Offline"
}
}
I have also tried replace Write-Verbose with Write-Host and Add-Content with Out-File but the problem I having is that no content / file is created when I use the full network path or share e.g. \\SERVERNAME\SHARENAME.$ the path identified has all the correct permissions and is being ran locally using the System account.
I wanted to see if the issue occured when writing the file locatlly consequently this does not happen when written to C:\Temp\
Does anyone have any ideas on to solve this.
I don't think that local system account has access to a network resource. I'm not sure if you have ever configured it or not. And what the command you used to run the command
Here I post a working way of doing this using Configuration Manager deployment after testing in my lab.
Basically I created a package with source files
and created a task sequence with single "Run Command Line" step.
The reason I use a task sequence is because I want to use an account to access the txt file on the network, which I can configure within a task sequence. I don't think Local System Account have such permission.
The script (DeactivateTest.ps1) I use as below just like what you provided and changed a little on the logic:
$Computer = hostname
foreach ($C in $Computer) {
if (Test-Connection $C -Quiet) {
Write-host "$C > Online"
$Users = Get-WMIObject Win32_UserAccount -Filter "LocalAccount=True" -ComputerName $C
$result=0
Foreach($user in $Users){
if ($User.Name -like '*test*') {
$username = $user.Name
"`n$(get-date -Format yyyymmdd_hhmmtt) User $username found ON $C, Disable 'test'" | Add-Content \\cas\resource\Result.txt
net user $username /active:no
$result+=1
}}
if($result =0){
"`n$(get-date -Format yyyymmdd_hhmmtt) User 'test' not found ON $C" | Add-Content \\cas\resource\Result.txt}
}
else {
"`n$C is Offline" | Add-Content \\cas\resource\Result.txt
}
}
The script query local account and disable accounts which have words "Test" in the name. If you don't like this logic, you can change :).
\\cas\resource\Result.txt is a txt file on the network share. Clients will write result to this txt file.
The command in the task sequence is (it's a x64 machine):
PowerShell.exe -ExecutionPolicy Bypass -File ".\DeactiveTest.ps1"
The output is like:
I may get downvoted for this as my answer isn't technically directly answering your question, it is, however, intended to try and point you in what may be a more logical direction. All apologies if I offend anyone, but here it is:
Why not just disable the user using Group Policy? If you really want to know where the user is/isn't disabled then you could just use hardware inventory for that, but GP really is the best way to enforce this kind of setting.

Adding Users to Groups from another Domain with Powershell

I have been tasked with creating a PowerShell script that copies Active Directory Group Memberships from a specified Source User (as a template) to a specified Target User. These users can be in one of two domains: Domain_A and Domain_B. The groups are all located in Domain_B.
The issue that I'm running into is that when I specify that both of the users are in Domain_A, it attempts to look for the groups in Domain_A, when in reality the groups are all in Domain_B (this throws an error saying that it can't find the groups). There is a 2 way trust between the domains as they are all located in the same forest.
How can I make it so that it will still specify the domains that the users are located in, but it will also specify the domain that the groups are located in? Here is a copy of my source code for reference (edited to remove the server names):
$Source_Server = Read-Host "Please enter the Source Server: "
$Source_UPN = Read-Host "Please enter the Source UPN: "
$Target_Server = Read-Host "Please enter the Target Server: "
$Target_UPN = Read-Host "Please enter the Target UPN: "
Try {
Get-ADUser -Identity $Source_UPN -Properties memberof -Server$Source_Server |
Select-Object -ExpandProperty memberof |
# Find Properties of the memberships of the Source User
Add-ADGroupMember -Members $Target_UPN -Server $Target_Server |
Select-Object -ExpandProperty SamAccountName
# Copy the group memberships of the Source User to the Target User.
}
Catch {
$Error_Message = $_.Exception.Message
Write-Host $Error_Message
Write-Host -NoNewLine "Press any key to exit..."
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
# Exits the program
}
If (!$Error) {
"Group Copy Successful."
$Error_Message = "No errors occured."
# Shows that it ran error-free
Write-Host -NoNewLine "Press any key to exit..."
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
# Exits the program
}
If you're trying to add the user in Domain B to the group in Domain A, you need to fix the Server parameter here to go to the Source Server:
Add-ADGroupMember -Members $Target_UPN -Server $Target_Server

Powershell - Batch Rename of Home Server in HomePath

Admittedly, I am not a PowerShell monster, so I'm going to punt...
I am working with a client who is pulling a list of all his user shares on his CIFS server to help redirect AD HomeDirectory paths in a major file server migration. This list is being compared to the list of AD users home directories as AD currently sees them.
The problem is that some user directories use old NT Usernames (NAMEI$) and some use SAMAACCOUNTNAME$. To Additionally complicate, the share SERVER differs in AD due to an elaborate history of DNS aliases over the past 10-15 years - so even though all the users home directories currently exist on SERVERA they could be mapped to OLDSERVER3, OLDERSERVER01, or OLDESTSERVERNT4 - resulting in home directories that are all over the map.
I need to write a script that can use the SAMACCOUNTNAME from a list, then change all the server information in the home directory to \NEWSEVERNAME\CURRENTSHARE$ - hopefully using something like this:
Use UserList
From UserList, get-ADuser -Identity $_ -HomeDrive "U:" -HomeDirectory
in HomeDirectory replace \\*\ with \\NewServer\ while leaving the Share$ untouched.
Set-ADuser -Identity $_ -HomeDrive "U:" -HomeDirectory
I'm fairly certain that this can be accomplished with regular expressions, for/each loops, etc... but I can't put it together.
Thank you for your help!
I went through the same migration a short while ago. Here is what you can use to set the new server while leaving the share folder untouched.
Import-Module activedirectory
$samAccountNameList = get-content "c:\userIds.txt"
$newServer = "newFps01"
foreach ($user in $samAccountNameList) {
$adProperties = get-aduser -Identity $user -Properties homeDirectory, homeDrive
$homeDrive = $adProperties.HomeDrive
# Split original homedirectory path and grab just the share folder portion
$shareFolder = ($adProperties.homeDirectory).Split("\")[3]
$newHomeDirectory = "\\$newServer\$shareFolder"
set-aduser -Identity $user -HomeDrive $homeDrive -HomeDirectory $newHomeDirectory
}