We have recently developed a Powershell script to automate the requirements for Exchange 2010 target setup. You can see the manual steps here. This script will setup a remote PowerShell session with an Exchange 2010 server and then prompt you for a name that will be used to create a windows account for use by the Migration Suite for Exchange.
The script has the following assumptions:
- The user name provided does not exist and needs to be created or the user name provided has been created already using this script and needs its setting refreshed.
- The User account provided to start the remote PowerShell session (script prompts for credentials) with the Exchange 2010 server has the necessary rights to execute the script. (NOTE: if this is a new installation you should you the user that was used to install Exchange 2010)
- Scripting is enabled in Windows PowerShell
- You are running this script from a host that has Windows PowerShell V2 and WinRM installed. (Note: Windows 7 already meets these requirements out of the box)
Below is the script and is also attached to this post as a downloadable attachment.
# This source code is provided "AS IS" with no warranties, and confers no rights
# Parts (c) 2010 by Priasoft, Inc
function Read-HostMasked([string]$prompt="Please provide your password") {
$password = Read-Host -AsSecureString $prompt;
$BSTR = [System.Runtime.InteropServices.marshal]::SecureStringToBSTR($password);
$password = [System.Runtime.InteropServices.marshal]::PtrToStringAuto($BSTR);
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR);
return $password;
}
Function Write-hostG([string] $Value)
{
$fore = $Host.UI.RawUI.ForegroundColor
$Host.UI.RawUI.ForegroundColor = "Green"
write-host $value
$Host.UI.RawUI.ForegroundColor = $fore
}
function New-SecureString([string] $plainText)
{
$secureString = new-object System.Security.SecureString
foreach($char in $plainText.ToCharArray())
{
$secureString.AppendChar($char)
}
$secureString
}
function Pause ($Message="Press any key to continue...")
{
# The ReadKey functionality is only supported at the console (not is the ISE)
if (!$psISE)
{
Write-Host -NoNewLine $Message
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Write-Host ""
}
}
write-host "Setup Exchange 2010 Power Shell Connection and create a new Migration User Account"
write-host "(c) 2010 Priasoft, Inc - Experts in Exchange-to-Exchange Migration"
write-host "Visit us on the web @ http://www.priasoft.com"
write-host "______________________________________________________________"
write-host ""
write-host "This script will do the following:"
write-host ""
write-host "Create a new user account (you will be prompted for the name) with an Exchange 2010 mailbox, create a new Exchange Throttling Policy for use only by this user, assign the new user to the policy, "
write-host "grant the new user rights to login to all mailboxes for existing databases, add the new user to the Builtin Administrators group on the domain,"
write-host "Add user to the Exch Organization Container with full rights,"
write-host "and add the new user to the Exchange 2010 Public Folder Management & Recipient Management role groups"
write-host ""
write-host ""
pause
write-host ""
Write-hostG "Please provide the host name of an Exchange 2010 server to connect to.."
write-host ""
# Get the Exchange host name of a 2010 server - loop for value if none provided
do {
$Server = read-host "Exchange 2010 server hostname (i.e. psex10)"
}
while($Server.Length -le 0)
write-host ""
Write-hostG "Please provide the domain\username of an existing account that has remote power shell right on the Exchange 2010 server"
Write-hostG "If this is a new install, you must provide the username that was used to install Exchange 2010"
write-host ""
# Get the Username - loop for value if none provided
do {
$userName = read-host "Enter username (i.e. Exch10\administrator)"
}
while($userName.Length -le 0)
write-host ""
$v = "Please enter password for " + $userName
Write-hostG $v
write-host ""
$Pass = Read-HostMasked
$Password = New-SecureString($Pass)
$fqdn = "http://" + $server + "/PowerShell/?serializationLevel=Full"
write-host ""
$v = "Starting remote Exchange 2010 Power Shell session on " + $fqdn
Write-hostG $v
write-host ""
Filter AssembleMessage ([String] $Path) { Add-Content -Path:"$Path" -Encoding:"Byte" -Value:$_.FileData }
Get-PSSession | Remove-PSSession
Get-Module | Remove-Module
$secureString = $Password
# by default connecting using kerberos auth
$UserCredential = New-Object System.Management.Automation.PSCredential -ArgumentList $userName,$secureString
$SkipCertificate = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $fqdn -Credential $UserCredential -Authentication kerberos -SessionOption $SkipCertificate
if($Session -eq $null){
throw write-host "Could not get Exchange 2010 session"
}
else {
#do nothing
}
write-host ""
Write-hostG "Please wait, importing session...."
write-host ""
Import-PSSession -Session $Session
write-host ""
Write-hostG "Please provide the name of the migration account you would like to create for use during the migration"
write-host ""
do {
$MigrationUserName = read-host -Prompt "Migration Account User Name <MigrationAdmin>"
}
while($MigrationUserName.Length -le 0)
# Note: You can change this if you like
$UPN = $MigrationUserName + "@migrationServiceAccount.com"
#
write-host ""
$v = "Looking for existing User " + $MigrationUserName + " with mailbox.."
Write-hostG $v
write-host ""
$NewMailbox = Get-mailbox -Identity $MigrationUserName
if($NewMailbox -eq $null){
Write-hostG "No user with mailbox Found.."
Write-Host ""
Write-hostG "Creating new user with mailbox.."
$NewMailbox = New-Mailbox -Alias $MigrationUserName -Name $MigrationUserName -Password $password -DisplayName $MigrationUserName -ResetPasswordOnNextLogon $False -RemotePowerShellEnabled $true -Force -UserPrincipalName $UPN
}
if($NewMailbox -eq $null){
Write-Host "Could not get/create new mailbox object"
quit
}
write-host ""
$v = "Looking for existing ThrottlingPolicy 'MigrationPolicy_NoLimits'"
Write-hostG $v
write-host ""
$pol = Get-ThrottlingPolicy -Identity 'MigrationPolicy_NoLimits'
if($pol -eq $null){
write-host ""
Write-hostG "Creating a new throttling policy for use by the new user"
write-host ""
$Pol = New-ThrottlingPolicy 'MigrationPolicy_NoLimits'
}
if($pol -eq $null){
Write-Host "Could not get/create new ThrottlingPolicy object"
quit
}
write-host ""
Write-hostG "Setting ThrottlingPolicy to RCAMaxConcurrency=0 and PowerShellMaxConcurrency=0"
write-host ""
Set-ThrottlingPolicy $pol -RCAMaxConcurrency $Null -PowerShellMaxConcurrency $Null
write-host ""
Write-hostG "Add new policy to user"
Set-Mailbox $NewMailbox -ThrottlingPolicy $pol
write-host ""
Write-hostG "Getting domain local group Administrators..."
write-host ""
$Group = Get-Group "administrators"
Write-hostG "Found domain local group Administrators"
write-host ""
write-host $group.grouptype
$UserDN = $NewMailbox.distinguishedName
$groupdn = $group.distinguishedName
$GroupSvr = $group.OriginatingServer
write-host ""
Write-hostG "Binding to local administrators group via ADSI to add new user"
write-host ""
$g = New-Object -TypeName DirectoryServices.Directoryentry -ArgumentList("LDAP://$GroupSvr/$groupdn",$username, $Pass)
Write-hostG "Bound to group via ADSI"
write-host ""
Write-hostG "Adding user " $UserDN
write-host ""
$g.member.add($userdn)
Try {
$g.psbase.CommitChanges()
Write-hostG "User Added"
write-host ""
}
Catch {
if ($error -like "*The object already exists*"){
write-hostg "User already a member"
# Do nothing
}
else {
write-host $error
}
}
Finally {
# Do nothing
}
Write-hostG "Locating exchange 2010 Org Object...."
write-host ""
$OClass = "msExchOrganizationContainer"
[String]$StrFilter = "(objectClass=$OClass)"
$objRootDSE = New-Object -TypeName DirectoryServices.Directoryentry -ArgumentList("LDAP://$GroupSvr/RootDSE",$username, $Pass)
[String]$strContainer = $objRootDSE.configurationNamingContext
[System.DirectoryServices.DirectorySearcher]$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = New-Object -TypeName DirectoryServices.Directoryentry -ArgumentList("LDAP://$GroupSvr/$strContainer",$username, $Pass)
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Subtree"
[System.DirectoryServices.SearchResult]$Result = $objSearcher.FindOne()
[System.DirectoryServices.DirectoryEntry]$De = $result.GetDirectoryEntry()
[string]$DnResult = $De.distinguishedName
Write-hostG "Adding user to Org Object with Send-as and Receive-As"
write-host ""
Add-ADPermission -Identity $DNResult -User $UserDN -AccessRights ExtendedRight -ExtendedRights Send-As, Receive-As -InheritanceType All
Write-hostG "Adding user to Org Object with Full Control"
write-host ""
Add-ADPermission -Identity $DNResult -User $UserDN -AccessRights GenericAll -InheritanceType All
Write-hostG "Add new user with admin access to all mailbox databases"
write-host ""
Get-MailboxDatabase | Add-ADPermission -User $UserDN -AccessRights ExtendedRight -ExtendedRights Receive-As, ms-Exch-Store-Admin
Write-hostG "Adding user to Recipient Management role group.."
write-host ""
Add-RoleGroupMember -Identity "Recipient Management" -Member $UserDN
Write-hostG "Adding user to Public Folder Management role group.."
write-host ""
Add-RoleGroupMember -Identity "Public Folder Management" -Member $UserDN
write-host ""
Write-hostG "Done!"
pause