FIM / MIM Preparation Script Version 1
Updated 23 September 2016 MIMPrepScript.zip
For the past few weeks my colleague and I who co author this blog have been working on a script to assist in the preparation and prerequisites to install FIM or MIM on your network. The goal is to complete as much of the labor intensive steps as possible that are often forgotten, the following is a list of task that are currently completed with this script.
- Create Organization Units if Needed
- Creating Service Accounts for
- Standard Synchronization and with the Portal
- Privileged Access Management
- Sets Permission on Organization Units
- Sets Permissions at Root of Domain
- Sets SPN's
- Creates DNS Records
- Creates Admin Groups
As the Script is updated additional task will be added as well as existing tasks will be tweaked and updated. Please keep in mind this is a work in progress and we are looking forward to your comments about this Script. Every effort has been made to ensure that this script does everything as advertised but considering every environment is different there may be complications. Please Respond with any questions, concerns or ideas that you would like to be added in this script. Most importantly use this script in a Lab Environment
Additionally this script is designed to work with the SharePoint Foundations 2013 Configuration Script that has already been posted.
- Download the Package
- Update the MIMPrepScript_Base.csv file with the information requested.
- Run the MIMPrepScript.ps1 Script
- Save MIMPrepScript_Base.csv file and use it with the SharePoint Foundations 2013 Configuration Script
I have Just completed testing on this script and I have had consistent results, please let me know if you have errors.
Before you use this script:
- Script is tested in a Dev or Test Environment
- Script must be run with credentials of an account with permissions to make the necessary changes in Active Directory
- The feeder file is completed with as much information as possible I have highlighted the required fields, keep in mind that is if all options are selected during the install.
- Review feeder file and fill in as much as possible
- Get updated files MIMPrepScript.zip
Note:
Occasionally when coping and pasting a script text is changed, I have noticed that the spn portions sometimes have issues coping over.
Script
#### Load Modules
### Load Active Directory Module
##########################################################################
if(@(get-module | where-object {$_.Name -eq "ActiveDirectory"} ).count -eq 0) {import-module ActiveDirectory}
#### Import Feeder File
##########################################################################
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
$dialog = New-Object -TypeName System.Windows.Forms.OpenFileDialog
$dialog.AddExtension = $true
$dialog.Filter = 'CSV file (*.csv)|*.csv|All Files|*.*'
$dialog.Multiselect = $false
$dialog.FilterIndex = 0
$dialog.InitialDirectory = "$HOME\Documents"
$dialog.RestoreDirectory = $true
$dialog.ShowReadOnly = $true
$dialog.ReadOnlyChecked = $false
$dialog.Title = 'Select Pre Req CSV file'
$result = $dialog.ShowDialog()
if ($result -ne 'OK')
{
return
}
$accts = Import-Csv $dialog.FileName
##Functions Prompt for input
function Prompt-ForInput
{
Param($message)
$success = "n"
#while($success -ne "" -and $success.ToUpper() -ne "YES")
while($success -ne “” -and $success.ToLower() -ne “1”)
{
$val = Read-Host $message
##$success = Read-Host "You entered: $val. Is this correct? Enter Yes or No"
$success = Read-Host “You entered: $val. Is this correct? Enter the #1 for Yes or the # 2 for No”
}
return $val
}
#### Questios that define configuration
### Questions
##########################################################################
$OrganizationalUnits = Prompt-ForInput "Do You need OU's Created Type 'Yes' or 'No'"
$SecurityGroups = Prompt-ForInput "Do you need the Synchronization Service Security Groups Installed Type 'Yes' or 'No'"
$ServiceAccounts = Prompt-ForInput "Do you need Service Accounts Created Type 'Yes' or 'No'"
if($ServiceAccounts.ToUpper() -eq "YES")
{
$SSPRConfiguration = Prompt-ForInput "Will you be Installing SSPR Features Type 'Yes' or 'No'"
$PAMConfiguration = Prompt-ForInput "Will be be installing the PAM Features Type 'Yes' or 'No'"
}
If($PAMConfiguration.ToUpper() -eq "YES")
{
$SetRegistry = Prompt-ForInput "Do You set Registry for SID History Migration Type 'Yes' or 'No'"
}
if($OrganizationalUnits.ToUpper() -eq "NO" -and $ServiceAccounts.ToUpper() -eq "NO" -and $SecurityGroups.ToUpper() -eq "NO")
{
Exit
}
### Variables
##########################################################################
## DOMAINVAR Gets reference to Domain Object to be referenced when needed as opposed to looking up each time.
$DomainVAR = Get-ADDomain
$Domain = $DomainVAR.NetBIOSName
$DomainDN = $DomainVAR.DistinguishedName
$DomainDNSR = $DomainVAR.DNSRoot
##Set Variables based on accts CSV
foreach($acct in $accts)
{
if($acct.variable -eq "MIMService")
{
$MIMService = $acct.SamAccountName
}
elseif($acct.variable -eq "MIMSPPool")
{
$MIMSPPool = $acct.SamAccountName
}
elseif($acct.variable -eq "ADMA")
{
$ADMA = $acct.SamAccountName
}
elseif($acct.variable -eq "MIMSync")
{
$MIMSSync = $acct.SamAccountName
}
elseif($acct.variable -eq "MIMPWDRST")
{
$MIMPWDRST = $acct.SamAccountName
}
elseif($acct.variable -eq "MIMPWDREG")
{
$MIMPWDREG = $acct.SamAccountName
}
elseif($acct.variable -eq "MIMAdmin")
{
$MIMAdmin = $acct.SamAccountName
}
elseif($acct.variable -eq "MIMMA")
{
$MIMMA = $acct.SamAccountName
}
elseif($acct.variable -eq "MIMSQL")
{
$MIMSQLSVC = $acct.SamAccountName
}
elseif($acct.variable -eq "MIMServiceSVR")
{
$MIMServiceSVR = $acct.Value
}
elseif($acct.variable -eq "MIMPortalSVR")
{
$MIMPortalSVR = $acct.Value
}
elseif($acct.variable -eq "PWDRegSVR")
{
$PWDREGSite = $acct.DisplayName
$PWDRegSVR = $acct.Value
$PWDRegIP = $acct.IP
}
elseif($acct.variable -eq "PWDResetSVR")
{
$PWDResetSite = $acct.DisplayName
$PWDResetSVR = $acct.Value
$PWDResetIP = $acct.IP
}
elseif($acct.variable -eq "MIMSyncSVR")
{
$SyncSVR = $acct.Value
}
elseif($acct.value -eq "BaseMIMDN")
{
$BASEMIMOU = $acct.DisplayName
$BaseMIMDN = "OU="+$BASEMIMOU+","+$DomainDN
}
elseif($acct.value -eq "BaseServiceDN")
{
$BaseServiceOU = $acct.DisplayName
$BaseServiceDN = "OU="+$BaseServiceOU+","+$DomainDN
}
elseif($acct.variable -eq "BaseUserDN")
{
$MIMUsersOU = $acct.DisplayName
$MIMUsersDN = "OU="+$MIMUsersOU+","+$BaseMIMDN
}
elseif($acct.variable -eq "BaseGroupDN")
{
$MIMGroupsOU = $acct.DisplayName
$MIMGroupsDN = "OU="+$MIMGroupsOU+","+$BaseMIMDN
}
elseif($acct.variable -eq "MIMSQLSVR")
{
$SQLSVR = $acct.DisplayName
}
elseif($acct.value -eq "CORP")
{
$CorpDCIP = $acct.ip
$CorpDC = $acct.DisplayName
}
elseif($acct.value -eq "PRIV")
{
$PrivDCIP = $acct.ip
$PrivDC = $acct.DisplayName
}
}
#### Build Functions
##########################################################################
function Create-OUs
{
New-ADOrganizationalUnit -Name $BASEMIMOU -Path $DomainDN
New-ADOrganizationalUnit -Name $BaseServiceOU -Path $DomainDN
New-ADOrganizationalUnit -Name $MIMUserSOU -Path $BASEMIMDN
New-ADOrganizationalUnit -Name $MIMGroupsOU -Path $BASEMIMDN
}
function Create-ServiceAccountsBasic
{
foreach($acct in $accts)
{
if($acct.Type -eq "Service Account Basic")
{
$sam = $acct.SamAccountName
$existingUser = Get-ADuser -Filter {SamAccountName -eq $sam}
if($existingUser -ne $null)
{
Write-Host "$($acct.SamAccountName) Already exists. Skipping account creation"
continue
}
$UserPrincipalName = $acct.SamAccountName + "@" + $domain
New-ADUser -SamAccountName $acct.SamAccountName -UserPrincipalName $UserPrincipalName -Name $acct.DisplayName -DisplayName $acct.DisplayName -Path $BaseServiceDN -AccountPassword (ConvertTo-SecureString "Password@123" -AsPlainText -force) -Enabled $True -ChangePasswordAtLogon $True -PassThru | Out-Null
}
}
}
function Create-ServiceAccountsSSPR
{
foreach($acct in $accts)
{
if($acct.Type -eq "Service Account SSPR")
{
$sam = $acct.SamAccountName
$existingUser = Get-ADuser -Filter {SamAccountName -eq $sam}
if($existingUser -ne $null)
{
Write-Host "$($acct.SamAccountName) Already exists. Skipping account creation"
continue
}
$UserPrincipalName = $acct.SamAccountName + "@" + $domain
New-ADUser -SamAccountName $acct.SamAccountName -UserPrincipalName $UserPrincipalName -Name $acct.DisplayName -DisplayName $acct.DisplayName -Path $BaseServiceDN -AccountPassword (ConvertTo-SecureString "Password@123" -AsPlainText -force) -Enabled $True -ChangePasswordAtLogon $True -PassThru | Out-Null
}
}
}
function Create-ServiceAccountsPAM
{
foreach($acct in $accts)
{
if($acct.Type -eq "Service Account PAM")
{
$sam = $acct.SamAccountName
$existingUser = Get-ADuser -Filter {SamAccountName -eq $sam}
if($existingUser -ne $null)
{
Write-Host "$($acct.SamAccountName) Already exists. Skipping account creation"
continue
}
$UserPrincipalName = $acct.SamAccountName + "@" + $domain
New-ADUser -SamAccountName $acct.SamAccountName -UserPrincipalName $UserPrincipalName -Name $acct.DisplayName -DisplayName $acct.DisplayName -Path $BaseServiceDN -AccountPassword (ConvertTo-SecureString "Password@123" -AsPlainText -force) -Enabled $True -ChangePasswordAtLogon $True -PassThru | Out-Null
}
}
}
function Create-SecurityGroups
{
#Param($CSGacct)
foreach($acct in $accts)
{
if($acct.Type -eq "Security Group")
{
$sam = $acct.SamAccountName
# $existingUser = Get-ADGroup -Filter {SamAccountName -eq $sam}
# if($existingUser -ne $null)
# {
# Write-Host "$($acct.SamAccountName) Already exists. Skipping account creation"
# continue
# }
##New-ADGroup -SamAccountName $acct.SamAccountName -UserPrincipalName $UserPrincipalName -Name $acct.DisplayName -DisplayName $acct.DisplayName -Path $BaseServiceDN -GroupScope Global -GroupCategory Security
New-ADGroup -Path $BaseServiceDN -Name $acct.DisplayName -GroupScope Global -GroupCategory Security
}
}
}
function Create-DNS-Records
{
foreach($acct in $accts)
{
if($acct.Type -eq "DNSRecord")
{
$DomainVAR = Get-ADDomain
$Domain = $DomainVAR.Name
$DomainDN = $DomainVAR.DistinguishedName
$DomainDNSR = $DomainVAR.DNSRoot
$DNSName = $acct.DisplayName
$DNSServer = $PrivDC
$Zone = $DomainDNSR
$DNSRecord =
$DNStype = "A"
$DNSRecordIP = $acct.IP
$Class = 1
$ttl = 3600
Add-DnsServerResourceRecordA -Name $DNSName -ZoneName $Zone -AllowUpdateAny -IPv4Address $DNSRecordIP -TimeToLive 01:00:00
}
}
}
function Set-Registry
{
New-ItemProperty –Path HKLM:SYSTEM\CurrentControlSet\Control\Lsa –Name TcpipClientSupport –PropertyType DWORD –Value 1
}
function Set-Permissionsbasic
{
### Delegate Permissions at the Root of the Domain
# Delegate Replicating Directory Changes
dsacls "$DomainDN" /G "$Domain\$($ADMA):CA;Replicating Directory Changes";
# Delegate access to the MIM Web Service in order to execute PowerShell scripts against AD directly
# Delegate Read/Write for userAccountControl
dsacls "$DomainDN" /G "$Domain\$($MIMService):RPWP;userAccountControl;user" /I:S
dsacls "$DomainDN" /G "$Domain\$($MIMService):RPWP;member;group" /I:S
### Delegate Permissions fot OU's that will contain MIM Managed Objects
##Delegat Permissions to the MIM Managed Users OU
# Delegate Create/Delete Users to the container that will manage Users
dsacls "$MIMUsersDN" /G "$Domain\$($ADMA):CCDC;user"
# Delegate Read/Write All Properties
dsacls "$MIMUsersDN" /G "$Domain\$($ADMA):RPWP;"
dsacls "$MIMUsersDN" /G "$Domain\$($ADMA):RPWP;userAccountControl;user" /I:S
##Delegate Permissions to the MIM Managed Groups OU
# Delegate Create, Delete, and Manage Groups to the Container to allow the ADMA Service Account that will manage Groups
dsacls "$MIMGroupsDN" /G "$Domain\$($ADMA):CCDC;group"
# Delegate Modify Memberships of Groups to the Container to allow the ADMA Service Account that will manage Groups
dsacls "$MIMGroupsDN" /i:s /g "$Domain\$($ADMA):rpwp;member;group"
###Set Kerberos Delegations###
##corp\ServiceAccounts Variables
$DomainMIMSVC = "$Domain\$MIMService"
$DomainMIMSPPool = "$Domain\$MIMSPPool"
##MIMService/(Server MIM Service is installed on) Variables
$MIMServiceSPN = "$MIMService/$MIMServiceSVR"
$MIMServiceSPNFQDN = "$MIMServiceSPN.$DomainDNSR"
## HTTP//(Server MIM Service is installed on)
$SPserviceSPN = "HTTP/$MIMServiceSVR"
$SPserviceSPNFQDN = "$SPserviceSPN.$DomainDNSR"
## Password Registration Variables
$PasswordRegDNS = "$PWDREGSite.$DomainDNSR"
$PasswordRegDNSSPN = "HTTP/$PasswordRegDNS"
$PWDRegSVRSPN = $PWDRegSVR+"$"
$PRDRegSVRDOM = "$Domain\$PWDRegSVRSPN"
## Password Reset Variables
$PasswordResetDNS = "$PWDResetSite.$DomainDNSR"
$PasswordResetDNSSPN = "HTTP/$PasswordResetDNS"
$PWDResetSVRSPN = $PWDResetSVR+"$"
$PRDResetSVRDOM = "$Domain\$PWDResetSVRSPN"
## SQL Server Variables
#### Set SPN's
#### https://technet.microsoft.com/en-us/library/jj134299(v=ws.10).aspx
### Set the SPNs for CORP\SPService
##Setspn.exe –S HTTP/fim1 CORP\SPService
Setspn.exe -S $SPserviceSPN $DomainMIMSPPool
##Setspn.exe –S HTTP/fim1.corp.contoso.com corp\SPService
##Setspn –S HTTP/FIM1.corp.contoso.com corp\SPService
Setspn.exe -S $SPserviceSPNFQDN $DomainMIMSPPool
### Set the SPNs for CORP\FIMService
##Setspn.exe –S FIMService/fim1 CORP\FIMService
setspn.exe -S $MIMServiceSPN $DomainMIMSVC
##Setspn.exe –S FIMService/fim1.corp.contoso.com CORP\FIMService
setspn.exe -S $MIMServiceSPNFQDN $DomainMIMSVC
### Set the SPNs for CORP\SQLDatabase
## Get with your SQL ADMIN to verify this has been completed
##Setspn –S MSSQLsvc/app1.corp.contoso.com:1433 corp\sqldatabase
##Setspn –S MSSQLsvc/app1:1433 corp\sqldatabase
### Set the SPNs for CORP\FIM2$
#$Setspn.exe –S HTTP/Passwordreset.corp.contoso.com CORP\FIM2$
setspn.exe -S $PasswordRegDNSSPN $PRDRegSVRDOM
#$Setspn.exe –S HTTP/Passwordregistration.corp.contoso.com CORP\FIM2$
setspn.exe -S $PasswordResetDNSSPN $PRDResetSVRDOM
}
#### Scripts
##########################################################################
## Create Organizational Units
if($OrganizationalUnits.ToUpper() -eq "YES")
{
Create-OUs
}
## Create Service Accounts
if($ServiceAccounts.ToUpper() -eq "YES")
{
if($acct.Type -eq "Service Account Basic")
{
Create-ServiceAccountsBasic
}
if($SSPRConfiguration -eq "YES")
{
Create-ServiceAccountsSSPR
}
if($PAMConfiguration -eq "YES")
{
Create-ServiceAccountsPAM
}
}
## Create Security Groups
if($SecurityGroups.ToUpper() -eq "YES")
{
Create-SecurityGroups
}
## Set up PAM
if($PAMConfiguration.ToUpper() -eq "YES")
{
If($SetRegistry -eq "YES")
{
Set-Registry
}
}
## Set Permissions for Service Accounts
if($ServiceAccounts.ToUpper() -eq "YES")
{
Set-Permissionsbasic
if($SSPRConfiguration.ToUpper() -eq "YES")
{
Create-DNS-Records
}
}
Comments
- Anonymous
August 11, 2016
The script fails on Server 2012 R2.Fails to create the Delegation (Unknown switch /G)SPN creation fails. - Wrong Syntax - Anonymous
August 12, 2016
@Adam the script has been tested on 2012 R2 could you please provide additional detail on the error you are receiving I would love to help you but more details are needed.1. Are you running elevated credentials?2. Was the Script copied and pasted?3. Were correct modules loaded?4. Did you use PowerShell ISE to step through the code?- Anonymous
September 19, 2016
Hi Anthony,I am getting an error in regards to $DomainNC not being defined. Are you able to assist?Thanks..- Anonymous
September 21, 2016
I will be uploading a new version Friday, there were a few errors caused with text migration in the previous script
- Anonymous
- Anonymous
- Anonymous
August 16, 2016
The comment has been removed - Anonymous
October 05, 2016
Thanks for the script Anthony .. helpful on my journey of prepping for DSC scripts....I am having trouble with the Reset and Reg SPN as well. Why the $ suffix? I found https://blogs.msdn.microsoft.com/connector_space/2015/11/10/fim-mim-preperation-script-version-1/ taht alluded to differences between 2003/2008/12 but unsure of suggested fix. There is no reference the SPN $ suffix in the MIM handbookAlso need to change script from ## Create Service Accounts if($ServiceAccounts.ToUpper() -eq "YES") { if($acct.Type -eq "Service Account Basic") - REMOVE as it was hitting the last acct = FABDC01 and skipping AND the first check in Create-ServiceAccountsBasic function is to if($acct.Type -eq "Service Account Basic") { Create-ServiceAccountsBasic to ## Create Service Accounts if($ServiceAccounts.ToUpper() -eq "YES") { Create-ServiceAccountsBasic } if($SSPRConfiguration -eq "YES") { Create-ServiceAccountsSSPR }Many thanksNigel- Anonymous
October 06, 2016
there has been some weird activity around that part of the code, often when building the variable that is used for that SPN it shows up as command unrecognized, if i retyped the command exactly as it was it works..all characters remain the same. but i was getting a different result. I thought i had this resolved but i will look into it further.
- Anonymous