Deploying Active Directory Federation Services

This guide describes how you can deploy Microsoft Active Directory Federation Services (AD FS) for Windows Server 2019 in a Managed Microsoft AD domain.

The following diagram illustrates the deployment:

Architecture

Users communicate with an HTTPS load balancer that uses a Google-managed certificate to terminate SSL connections. The load balancer forwards connections to a VM instance that runs Microsoft AD FS for Windows Server 2019 and that is joined to Managed Microsoft AD domain. Communication between the load balancer and the VM instance is secured by using a self-signed SSL certificate.

The deployment uses a single AD FS instance and the Windows Internal Database, which makes it suitable for small environments. For environments with increased reliability or security demands, consider deploying multiple AD FS instances in a farm configuration and deploying federation proxies.

Before you begin

To complete this guide, you need the following:

Make sure you're familiar with the requirements for deploying AD FS.

Preparing the project and network

You now prepare your Google Cloud project and VPC for the deployment of AD FS.

Create a VM instance

Create a service account and VM instance to run AD FS:

  1. In the console, open Cloud Shell.

    Activate Cloud Shell

  2. Initialize the following variables:

    VPC_NAME=VPC_NAME
    SUBNET_NAME=SUBNET_NAME
    

    Where:

    • VPC_NAME is the name of your VPC.
    • SUBNET_NAME is the name of the subnet to deploy AD FS in.
  3. Set your default project ID:

    gcloud config set project PROJECT_ID
    

    Replace PROJECT_ID with the ID of your Google Cloud project.

  4. Set your default region and zone:

    gcloud config set compute/region REGION
    gcloud config set compute/zone ZONE
    

    Where:

    • REGION is the ID of the region you want to deploy in.
    • ZONE is the ID of the zone you want to deploy in.
  5. Create a service account:

    gcloud iam service-accounts create ad-federation-services
    
  6. Create a VM instance that runs Windows Server 2019 and uses a specialize script to automatically install the AD FS server role:

    gcloud compute instances create adfs-1 \
      --machine-type n2-standard-8 \
      --image-family windows-2019 \
      --image-project windows-cloud \
      --boot-disk-size 50 \
      --boot-disk-type pd-ssd \
      --subnet $SUBNET_NAME \
      --service-account ad-federation-services@$(gcloud config get-value core/project).iam.gserviceaccount.com \
      --metadata sysprep-specialize-script-ps1="Add-WindowsFeature ADFS-Federation -IncludeManagementTools;Add-WindowsFeature RSAT-AD-PowerShell;Add-WindowsFeature RSAT-ADDS-Tools"
    
    1. Monitor the initialization process of the VM by viewing its serial port output:

      gcloud compute instances tail-serial-port-output adfs-1
      

      Wait about 3 minutes until you see the output Instance setup finished, then press Ctrl+C. At this point, the VM instance is ready to be used.

    2. Create a username and password for the VM instance

    3. Connect to the VM by using Remote Desktop and log in using the username and password created in the previous step.

    4. Right-click the Start button (or press Win+X) and click Windows PowerShell (Admin).

    5. Confirm the elevation prompt by clicking Yes.

    6. Join the computer to your Active Directory domain and restart:

      Add-Computer -Domain DOMAIN -Restart
      

      Replace DOMAIN with the DNS name of your Active Directory domain.

      Wait for approximately 1 minute for the restart to complete.

Create a load balancer

You now create a load balancer that lets users access AD FS by using a single virtual IP address.

To associate the VM instance that runs AD FS with the load balancer, you first create an unmanaged instance group, and then assign this instance group to the load balancer:

  1. Return to your existing Cloud Shell session.
  2. Create the unmanaged instance group:

    gcloud compute instance-groups unmanaged create adfs &&
    gcloud compute instance-groups set-named-ports adfs --named-ports=http:443
    
  3. Add the existing VM instance to the instance group:

    gcloud compute instance-groups unmanaged add-instances adfs --instances adfs-1
    
  4. Create a health check that probes the HTTPS port of AD FS:

    gcloud compute health-checks create tcp adfs-health-check --port 443
    
  5. Create a load balancer backend service that uses the HTTPS health check and instance group that you created previously:

    gcloud compute backend-services create adfs-backend \
      --health-checks adfs-health-check \
      --port-name http \
      --protocol HTTPS \
      --global && \
    gcloud compute backend-services add-backend adfs-backend \
      --instance-group adfs \
      --global \
      --instance-group-zone $(gcloud config get-value compute/zone)
    
  6. Reserve a static external IP address for the load balancer:

    gcloud compute addresses create adfs-external --global
    
  7. Create a managed SSL certificate for the load balancer:

    gcloud compute ssl-certificates create adfs-external \
      --domains PUBLIC_FQDN \
      --global
    

    where PUBLIC_FQDN is the public, fully qualified domain name (FQDN) that you want to use for AD FS, for example login.example.com.

  8. Create a load balancer frontend that uses the external IP address and forwards traffic to the backend service:

    gcloud compute url-maps create adfs \
      --default-service adfs-backend && \
    gcloud compute target-https-proxies create adfs-proxy \
      --ssl-certificates adfs-external \
      --url-map adfs && \
    gcloud compute forwarding-rules create adfs \
      --global \
      --address adfs-external \
      --target-https-proxy adfs-proxy \
      --ports 443
    
  9. Create a firewall rule to allow traffic from the load balancer to the VM instance that runs AD FS:

    gcloud compute firewall-rules create allow-https-to-adfs \
      --allow tcp:443 \
      --network $VPC_NAME \
      --source-ranges 130.211.0.0/22,35.191.0.0/16 \
      --target-service-accounts ad-federation-services@$(gcloud config get-value core/project).iam.gserviceaccount.com
    

    The source ranges are the IP ranges for the internal load balancer. For more information, see Configure a firewall rule.

  10. Look up the IP address of the load balancer:

    gcloud compute addresses describe adfs-external \
       --global \
       --format=value\(address\)
    
  11. Create a DNS A record in your public DNS zone that points to the IP address of the load balancer. The fully qualified name of the DNS record must match the name that you used for the SSL certificate.

Deploying AD FS

You now deploy the AD FS server role on the VM instance adfs-1. Because you don't have domain admin rights in a Managed Microsoft AD domain, you can't use Server Manager to perform the installation and must use PowerShell instead.

Create a service user

You now create a user account in Active Directory for the AD FS service:

  1. Connect to the VM instance adfs-1 by using Remote Desktop and log in using your delegated administrator credentials.
  2. Right-click the Start button (or press Win+X) and click Windows PowerShell (Admin).
  3. Set a random password for the AD FS service account:

    $AdfsCredential = Get-Credential -UserName adfssvc -Message 'Enter password'
    
  4. Create an Active Directory user adfssvc:

    $CloudOuPath = "OU=Cloud," + (Get-ADDomain).DistinguishedName
    $AdfsUser = New-ADuser `
      -Name adfssvc `
      -DisplayName 'AD FS service account' `
      -AccountPassword $AdfsCredential.Password `
      -Path "$CloudOuPath" `
      -PasswordNeverExpires $True `
      -PassThru | Enable-ADAccount -PassThru
    
  5. Add the user to the local Administrators group:

    Add-LocalGroupMember `
     -Group "Administrators" `
     -Member "$env:userdomain\adfssvc"
    
  6. Assign a service principal name:

    setspn -a http/PUBLIC_FQDN adfssvc
    

    where PUBLIC_FQDN is the public, fully qualified domain name of AD FS.

  7. Create an empty container in Active Directory. You use this container later when you install AD FS:

    New-ADObject `
      -Type Container `
      -Name "ADFS Data" `
      -Path $CloudOuPath
    
  8. Grant the AD FS user full control on the container:

    dsacls.exe "CN=ADFS Data,$CloudOuPath" /G $env:userdomain\adfssvc:GA /I:T
    

Install AD FS

You now install AD FS on adfs-1:

  1. Start a PowerShell session as the ADFS user:

    runas /u:$env:userdomain\adfssvc powershell
    

    The new PowerShell session now runs as the AD FS user, but without elevated privileges.

  2. In the new PowerShell session, start a second, elevated PowerShell session:

    Start-Process PowerShell -Verb RunAs
    

    You must run all subsequent steps in this new, elevated PowerShell session.

  3. Create a self-signed SSL certificate that uses an RSA 2048 bit key and store it in the computer certificate store:

    $DnsName="PUBLIC_FQDN"
    $Certificate = New-SelfSignedCertificate `
      -Subject $DnsName `
      -KeyAlgorithm RSA `
      -KeyLength 2048 `
      -KeyExportPolicy NonExportable `
      -KeyUsage DigitalSignature, KeyEncipherment `
      -Provider 'Microsoft Platform Crypto Provider' `
      -NotAfter (Get-Date).AddDays(365) `
      -Type SSLServerAuthentication `
      -CertStoreLocation 'Cert:\LocalMachine\My' `
      -DnsName $DnsName
    

    where PUBLIC_FQDN is the public, fully qualified domain name of AD FS.

  4. Create another RSA 2048 bit certificate that AD FS uses as token signing certificate:

    $SigningCertificate = New-SelfSignedCertificate `
      -Subject "ADFS Signing" `
      -KeyAlgorithm RSA `
      -KeyLength 2048 `
      -KeyExportPolicy NonExportable `
      -KeyUsage DigitalSignature, KeyEncipherment `
      -Provider 'Microsoft RSA SChannel Cryptographic Provider' `
      -NotAfter (Get-Date).AddDays(365) `
      -DnsName $DnsName `
      -CertStoreLocation 'Cert:\LocalMachine\My'
    
  5. Create a Distributed Key Manager (DKM) container:

    $CloudOuPath = "OU=Cloud," + (Get-ADDomain).DistinguishedName
    $DkmContainer = New-ADObject `
      -Name ((New-Guid).Guid) `
      -Type Container `
      -Path "CN=ADFS Data,$CloudOuPath" `
      -PassThru
    
  6. Re-enter the credentials for the AD FS user that you set previously:

    $AdfsCredential = Get-Credential -UserName "$env:userdomain\adfssvc" -Message 'Enter password'
    
  7. Install AD FS using the certificates and DKM container that you created previously:

    Install-ADFSFarm `
      -CertificateThumbprint $Certificate.Thumbprint `
      -SigningCertificateThumbprint $SigningCertificate.Thumbprint `
      -DecryptionCertificateThumbprint $SigningCertificate.Thumbprint `
      -FederationServiceName $DnsName `
      -ServiceAccountCredential $AdfsCredential `
      -OverwriteConfiguration `
      -AdminConfiguration @{"DKMContainerDn"=$DkmContainer.DistinguishedName}
    

    The command might show the following warning messages:

    WARNING: A machine restart is required to complete ADFS service configuration. For more information, see:
    https://go.microsoft.com/fwlink/?LinkId=798725
    
    WARNING: The SSL certificate subject alternative names do not support host name 'PUBLIC_FQDN'.
    Configuring certificate authentication binding on port '49443' and hostname 'PUBLIC_FQDN'.
    
    WARNING: An error occurred during an attempt to set the SPN for the specified service account. Set the SPN for the
    service account manually.  For more information about setting the SPN of the service account manually, see the AD FS
    Deployment Guide.  Error message: An error occurred during an attempt to set the SPN for the specified service account.
    You do not have sufficient privileges in the domain to set the SPN.
    
    WARNING: The SSL certificate does not contain all UPN suffix values that exist in the enterprise.  Users with UPN
    suffix values not represented in the certificate will not be able to Workplace-Join their devices.  For more
    information, see http://go.microsoft.com/fwlink/?LinkId=311954.
    

    You can ignore these warnings because you've already set the SPN and aren't using certificate-based authentication.

  8. If you're planning to use Integrated Windows Authentication (IWA) to authenticate to AD FS, run the following command to disable token binding:

    Set-ADFSProperties –ExtendedProtectionTokenCheck None
    Restart-Service -Name adfssrv
    

    Disabling token binding is necessary because you're deploying AD FS behind a load balancer and the load balancer terminates TLS connections.

Configure TLS

When establishing connections to backends, the HTTPS load balancer doesn't use the server name indication (SNI) extension. To let AD FS accept connection without SNI, you must configure a certificate fallback:

  1. In PowerShell, view the SSL server certificate bindings for AD FS:

    netsh http show sslcert hostnameport=PUBLIC_FQDN:443
    

    where PUBLIC_FQDN is the public, fully qualified domain name of AD FS

  2. Configure a fallback certificate for the binding:

    netsh http add sslcert ipport=0.0.0.0:443 certhash=CERTIFICATE_HASH "appid=APP_ID" "certstorename=MY"
    

    Where:

    • CERTIFICATE_HASH is the certificate hash shown in the previous command.
    • APP_ID is the application ID shown in the previous command, including curly braces.
  3. Restart the computer to complete the installation:

    Restart-Computer
    

    Wait for approximately 1 minute for the restart to complete.

Testing AD FS

The AD FS service is now deployed, but you still have to verify that the service can be access via the HTTPS load balancer:

  1. Return to the Cloud Shell session.
  2. Verify that the SSL certificate is in state ACTIVE:

    gcloud compute ssl-certificates describe adfs-external \
        --global \
        --format="get(managed.status)"
    

    If the certificate is in state PROVISIONING, then the DNS record that you created for AD FS might require additional time to propagate. For further details, see Troubleshooting Google-managed certificates.

  3. On your local computer, open a browser and navigate to the following URL:

    https://PUBLIC_FQDN/adfs/ls?wa=wsignout1.0
    

    Replace PUBLIC_FQDN with the public, fully qualified domain name of AD FS

    Verify that you see a message You have successfully signed out, indicating that AD FS has been deployed successfully.

If you're planning to use Integrated Windows Authentication (IWA), verify that you can obtain a Kerberos ticket for AD FS:

  1. Connect to the VM instance adfs-1 or a different domain-joined VM by using Remote Desktop and log in using domain credentials.
  2. Right-click the Start button (or press Win+X) and click Windows PowerShell.
  3. Use the klist command to request a service ticket for AD FS:

    klist get http/PUBLIC_FQDN
    

    Verify that the output includes a ticket for AD FS:

    #1>     Client: USER @ DOMAIN
            Server: http/PUBLIC_FQDN @ DOMAIN
            KerbTicket Encryption Type: ...
    

AD FS is now ready to be used. For details on using and configuring the service, see AD FS Operations