In this article, I am continuing to deploy ADFS 2.1 on Windows Server 2012 to work with Office 365 (Wave 15). See Part 1 of this write-up for details on how to setup and verify your custom Office 365 domains using PowerShell, how to deploy the first ADFS 2.1 server using PowerShell, and how to enable a new Office 365 domain for federation and directory synchronization.
Just as a reminder, the main goal of this series of posts is to demonstrate:
- How to deploy AD FS 2.1 on Windows Server 2012 to work with Office 365
- How to deploy AD FS 2.1 in “Advanced Configuration”, which is required in some cases – for example, when your Active Directory environment exceeds 50,000 accounts. This currently must be done using PowerShell.
ADFS Topology Diagram
To make the setup easier to understand, we will work along the lines of this diagram:
In Part 1, we ended up with lab-adfs-01 server being deployed, and lab-sql-01 server used as ADFS configuration store. The next step is to join additional ADFS servers to the existing ADFS farm that uses SQL instead of WID.
Step 5: Join Additional ADFS 2.1 Servers to ADFS SQL Farm
Same as Step 3 in Part 1, we need to add required components to the ADFS server:
In elevated PowerShell:
Add-WindowsFeature NET-Framework-Core, ADFS-Federation
- Install msoidcli_64.msi (version 7.2 beta, see links at the beginning of the Par 1 post)
- Install AdministrationConfig-en.msi, 64-bit WAAD PowerShell module
- Add service-adfs to local administrators
- Copy sts.flexecom.com.pfx to Desktop
Certutil.exe -importpfx sts.flexecom.com.pfx
As part of the first ADFS server installation, a new SPN record was created on the ADFS farm service account, service-adfs. We have not checked that this operation succeeded in Part 1, as the focus of that post was on setting up the new federated domain in Office 365. But it does not hurt to check that SPN was added correctly:
setspn.exe -L service-adfs Registered ServicePrincipalNames for CN=service-adfs,CN=Users,DC=flexecom,DC=com: host/sts.flexecom.com
The “host/sts.flexecom.com” matches the name of our ADFS farm and is what we expected to see.
Optional: De-Elevate ADFS Service Account to Domain Users
For those who are practicing defense in depth and trying to keep their attack surfaces as narrow as possible, now is a good time to de-elevate ADFS farm service account from Domain Admins to Domain Users.
Domain Admin was necessary to install the first ADFS federation server into a new farm, because FsConfig.exe needed to create the SPN and certificate containers, as well as create new SQL databases. If you ran FsConfig.exe during the farm creation in the context of ADFS service account, then you had to have Domain Admin privileges on that account.
To de-elevate ADFS service account:
- Remove the service-adfs account from Domain Admins in the Active Directory
- Create a new SQL login for service-adfs on lab-sql-01, and ensure that it is mapped to AdfsConfiguration and AdfsArtifactStore databases as db_owner
- Double-check that service-adfs is a member of local Administrators group on all ADFS farm servers that are already deployed
Execute FsConfig to Join Existing Farm
Next step, let’s add a new ADFS farm member (elevated PowerShell):
C:\Windows\ADFS\FsConfig.exe JoinSQLFarm /serviceaccount FLEXECOM\service-adfs /sqlconnectionstring "database=AdfsConfiguration;Server=lab-sql-01.flexecom.lab;Integrated Security=SSPI" /certthumbprint "long sts.flexecom.com certificate thumbprint with spaces"
This command above is executed in the context of the de-elevated ADFS service account, and results in the following output:
Everything came back green, things are good. At this point my internal farm setup is nearly completed. What remains is minor configuration tweaks, and NLB load balancing.
Step 6: Ensure That Relying Party Trust is Updated Regularly
This step is completely optional, but is worth pointing out at this stage, now that our internal ADFS farm setup is nearly finished. From time to time, Microsoft may update their side of the federation trust. To ensure that these changes are monitored and applied automatically on our end, enable ADFS relying party trust monitoring:
Get-ADFSRelyingPartyTrust | Set-ADFSRelyingPartyTrust -AutoUpdateEnabled $true
While this setting is desirable to enable, it won’t help us a year from now, when token-signing certificates expire (remember the self-signed, automatically managed token-signing certificates?)
To update the Microsoft side of our ADFS relying party trust, and inform them of our self-signed certificate rollover, we will have to use one of the following two methods:
- Do it manually using WAAD PowerShell
- Connect-MsolService (provide credentials)
- Update-MsolFederatedDomain (this command updates the relying party trust)
- Do it automatically via a scheduled task with securely saved credentials
Automatic is the way to go, of course. Microsoft gives us a PowerShell script that installs this scheduled task, and stores MSOL credentials securely in the credential vault. This scripts is called Microsoft Office 365 Federation Metadata Update Automation Tool and it can be downloaded here.
Once you get the tool, drop your execution policy to allow this unsigned script to run (you may be able to run the tool without this step, depending on your UAC settings):
Then run the tool
This results in a prompt to confirm that you want to run the script, and the following output:
The tool asks for your ADFS service account credentials and MSOL (Office 365) administration credentials, writes out a script into C:\Office365-Scripts directory, and installs the scheduled task:
Triggering this task updates the Office 365 side of the relying party trust configuration. This task will run every midnight automatically, and it should be installed on one ADFS farm server. Keep in mind that every time your Office 365 admin password changes, or your ADFS farm service account password changes, you will need to re-run this installation task.
To test how well this works, run the following command in PowerShell to update self-signed certificates:
Update-ADFSCertificate -CertificateType "Token-Signing"
This command adds a new certificate to your side of the trust. Trigger the scheduled task, then execute the following command from the WAAD PowerShell:
Connect-MsolService Get-MsolFederationProperty -DomainName flexecom.com
You will see that the printout will show the new token signing certificate on the Microsoft Office 365 side.
Don’t forget to drop the script signing policy back to a more reasonable level:
Step 7: Deploy Load Balancing Between All ADFS Farm Servers
This step is completely optional in a lab, but an ADFS outage in production (especially with 50,000 accounts) could be tantamount to having an Exchange, Lync, Sharepoint, and file server outage all at the same time. Pretty disastrous. Hardware load balancers are preferred as they keep ADFS server configuration less cumbersome, but in the absence of a hardware load balancer, Windows Network Load Balancing will do just fine.
Add-WindowsFeature NLB, RSAT-NLB
We won’t go into the fine details of unicast NLB vs. multicast NLB, and discussions of how many NIC interfaces should really be deployed for a multicast NLB farm. One NIC is sufficient for our lab.
To get the names of interfaces, use this command:
To install the cluster on the first ADFS farm member:
New-NlbCluster -HostName lab-adfs-01 -ClusterName sts.flexecom.com -ClusterPrimaryIP 192.168.1.20 -SubnetMask 255.255.255.0 -OperationMode Multicast -InterfaceName Ethernet
To join additional cluster nodes from the same ADFS farm member where NLB cluster was created:
Add-NlbClusterNode -NewNodeName lab-adfs-02 -NewNodeInterface Ethernet -InputObject (Get-NlbCluster)
To add the second VIP to the NLB cluster (this will be needed later for IdP-Initiated Sign-On redirection website):
Add-NlbClusterVip -IP 192.168.1.30 -SubnetMask 255.255.255.0 -InputObject (Get-NlbCluster)
At this point, we have internal ADFS 2.1 farm on Windows Server 2012 configured for basic operation with Microsoft Office 365. We’ll take a break here – Part 3 will deal with ADFS Proxy installation and IdP-Initiated Sign-On redirection.