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.

  1. Create Organization Units if Needed
  2. Creating Service Accounts for
    1. Standard Synchronization and with the Portal
    2. Privileged Access Management
  3. Sets Permission on Organization Units
  4. Sets Permissions at Root of Domain
  5. Sets SPN’s
  6. Creates DNS Records
  7. 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.

  1. Download the Package
  2. Update the MIMPrepScript_Base.csv file with the information requested.
  3. Run the MIMPrepScript.ps1 Script
  4. 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 (7)

  1. 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 handbook

    Also 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 thanks

    Nigel

    1. 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.

  2. Fabien Huysmans says:

    Hi,

    i was reading the script before launching it … 😉 And i’ve found inside the function Set-PermissionBasic, that you’re using a variable $DomainNC which isn’t set inside the whole script !
    dsacls “$DomainNC” /G “$Domain\$($ADMA):CA;Replicating Directory Changes”;

    That’s giving me a good looking at how we can fully install MIM 2016, but that script is not working correctly without that variable correclty set

    Maybe you can make your script even better, with a password prompting (better than writing it down inside the script), also with leaving us the choice to manually add all users/groups by hand, and just giving the opportunities to create the DNS record, and the setspn settings using your csv file !

    Really good job

  3. @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?

    1. Jay Dave says:

      Hi Anthony,

      I am getting an error in regards to $DomainNC not being defined. Are you able to assist?

      Thanks..

      1. I will be uploading a new version Friday, there were a few errors caused with text migration in the previous script

  4. Adam Brown says:

    The script fails on Server 2012 R2.

    Fails to create the Delegation (Unknown switch /G)

    SPN creation fails. – Wrong Syntax

Skip to main content