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 Cloud 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 DNS_DOMAIN \
      --global
    

    where DNS_DOMAIN is the external DNS name that you want to use for AD FS. This domain name might be different from the domain names used by Active Directory.

  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 in 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 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/$env:userdomain adfssvc
    
  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="DNS_DOMAIN"
    $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 DNS_DOMAIN is the external DNS name that you want to use for AD FS. This domain name might be different from the domain names used by Active Directory.

  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}
    

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=DNS_DOMAIN:443
    

    where DNS_DOMAIN is the external DNS 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 https://DNS_DOMAIN/adfs/ls?wa=wsignout1.0 where DNS_DOMAIN is the external DNS name that you configured for AD FS.

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

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