HOWTO: Setup Microsoft ADFS as an SSO Provider for CloudBolt CMP

Overview

This document will go over the steps to create an ADFS Identity Provider capable of communicating with CloudBolt.

Considerations

pysaml2 has a fix that was uncommitted in version 4.9.0 that helps when communicating with ADFS using SHA-256 certificates referenced here:

https://github.com/IdentityPython/pysaml2/pull/597/commits/35555782a3640fc9700f2f2dd688f221b5e0ca82  

Since version 4.9.0 the code was committed into a later release (the most recent release at the time of this writing is 6.5.1 and the fix may have been introduced in 6.4.0 if I am reading the merge notes correctly HERE)

Upgrading to a supported pysaml2 version is required if you want to use SHA-256 certificates in the IdP and or with the SAML Service Provider (the CloudBolt server)

You will either need a fully configured ADFS Server or need to install ADFS using the below as a guideline in order to set up ADFS.

Note: How you setup the ADFS service account is not important as long as it is able to act administratively on the ADFS Server and delegate on the SSO DNS name you have chosen (the hostname of the computer, or something else like sso.yourdomainname.com)

While this is given as an example of how you could install ADFS, and configure it to work with CloudBolt, you don’t need to follow this exact procedure and it is given as an example of how you could do it. The Service Account could be created as an MSA (Managed Service Account) if you prefer and there are several choices like where to get a certificate from, and or if you want to set the SAML Signing to include the Message and Assertion or just the message itself which will change how you need to configure CloudBolt (based on the IdP’s configuration [ADFS]).

Making sure that the individual ADFS and CloudBolt servers are configured to syncronize time with an atomic clock in order to make sure that the SAML request is approved (because both servers times are in sync) is important, as well bercause “Clock Skew” will invalidate the data as well.

Definitions

adfs = the adfs service account name

adfsserver = the adfsserver computer name

SOMEDOMAIN = the NetBios Domain Name of your Active Directory Domain

somedomainname.com = the LDAP/DNS domain name for your Active Directory Domain

sso.somedomainname.com = alternate/vanity URL to connect to ADFS with (to mask the hostname you’ve configured ADFS for – also helpful if you are installing an ADFS farm [multiple servers handling ADFS authentication] in a DNS round-robin type setup)

cloudbolt.somedomainname.com = the URL that CloudBolt will be configured to listen on (this pertains to the CloudBolt “Portal” URL under Admin → System → Branding and Portals)

somepassword = a secure password that meets your company’s security policy for the given user account

Procedure

Most of the steps below are powershell scripts/commands

Step 1 - Join ADFS Server to the Active Directory Domain (if not already joined)

Step 2 - Edit Registry to Set .NET Framework subsystems to use Strong Crypto (TLS1.2)

New-ItemProperty -Path HKLM:\Software\Microsoft\.NetFramework\v2.0.50727 -Name SchUseStrongCrypto -Value 1 -PropertyType DWORD -Force

New-ItemProperty -Path HKLM:\Software\Microsoft\.NetFramework\v4.0.30319 -Name SchUseStrongCrypto -Value 1 -PropertyType DWORD -Force

New-ItemProperty -Path HKLM:\Software\Wow6432Node\Microsoft\.NetFramework\v2.0.50727 -Name SchUseStrongCrypto -Value 1 -PropertyType DWORD -Force

New-ItemProperty -Path HKLM:\Software\Wow6432Node\Microsoft\.NetFramework\v4.0.30319 -Name SchUseStrongCrypto -Value 1 -PropertyType DWORD -Force

  • After setting these items the server requires a reboot to make them active (if these registry entries were not already set)

  • Also note that we need to handle the registry key for both the 32-bit and 64-bit .NET Framework providers (Wow6432Node is the 32-bit registry key)

  • This enables communication on TLS 1.2 protocol to the CloudBolt server (a requirement for the CloudBolt server - TLS 1.0 is disabled in the CloudBolt server as a security measure against various security vulnerabilities present)

Step 3 - Create ADFS Service Account User in Active Directory

New-ADUser -Name "ADFS ServiceAccount" -GivenName "ADFS" -Surname "ServiceAccount" -SamAccountName "adfs" -UserPrincipalName "adfs@yourdomainname.com" -Path "CN=Users,DC=yourdomainname, DC=com" -AccountPassword(ConvertTo-SecureString -String "somesecurepassword” -AsPlainText -Force) -Enabled $true

Step 4 - Set the ServicePrincipalName(s) on the ADFS user account

Set-ADUser "adfs" -ServicePrincipalNames @{Add='HOST/sso.somedomainname.com','HTTP/sso.somedomainname.com','HTTP/adfsserver.yourdomainname.com'}

  • This defines what services we need to communicate through (the HOST and the HTTP Services - with those particular hostnames)

Step 5 - Enable the ADFS Service Account User to be “Trusted for Delegation” and set the password not to expire

Set-ADAccountControl "ADFS" -TrustedForDelegation $true -PasswordNeverExpires $true

Step 6 - Update the Delegation Model to be constrained and only allowed to delegate for particular SPNs (Service Principal Names)

Set-ADUser -Identity ADFS -Add @{'msDS-AllowedToDelegateTo'=@('HOST/sso.yourdomainname.com','HTTP/sso.yourdomainname.com','HTTP/adfsservername.yourdomainname.com')}

  • This will add entries to the constrained delegation (if any already exist) - constrained delegation is a more secure way of handling Kerberos delegation (the other option is to allow it to delegate on EVERY name/service (SPN) it is configured for - which might create issues if an attacker gets access to this system/user). Constrained Delegation is highly recommended from a least privilege configuration perspective.

Step 7 - Install Active Directory Federation Services (ADFS)

Install-WindowsFeature ADFS-Federation

Step 8 - Create DNS A Record for ADFS Server and the SSO URL (sso.somedomainname.com)

Note: this is optional but goes along with the use case above where we will be using sso.yourdomainname.com to connect to for authentication requests in the examples that follow, so it is required unless you are using the ADFS Server Computer Name as the authentication endpoint for your Identity Provider (IdP)

Step 9 - Request a certificate from your Enterprise Root Certificate Authority (or a publicly recognized certificate authority) and import it to your ADFS server under the Local Machine configuration

Note: This step is optional, as you can use a self-signed certificate, but you would then have Chrome/Mozilla/IE Certificate errors when communicating to this server. Creating a trusted Certificate Chain is strongly advised.

Optionally, you can create and install a self-signed certificate for the procedure in Step 11 (not advised)

Step 10 - Add the ADFS Domain service account to the Local Administrators Group of the ADFS Server

net localgroup "Administrators" /add "SOMEDOMAIN\adfs"

Step 11 - Install the ADFS “FARM” using a Domain Admin account, and setting the ADFS FARM to use the Service Account provided with the certificate created/installed earlier

$thumbprint = (dir Cert:\LocalMachine\My| Select * | Where-Object {$_.{Subject} -eq "cn=sso.somedomainname.com"}).Thumbprint

$Cred = (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "SOMEDOMAIN\Administrator", (ConvertTo-SecureString "somepassword" -AsPlainText -Force))
$SACred = (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "SOMEDOMAIN\adfs", (ConvertTo-SecureString "somepassword" -AsPlainText -Force))

Install-ADFSFarm -CertificateThumbprint $thumbprint -FederationServiceName "sso.somedomainname.com" -ServiceAccountCredential $SACred -Credential $Cred

Step 12 - Creating Windows Integrated Authentication mappings for Chrome and IE

Note: This step is optional and allows Authentication to be passed from the the logged in user’s credentials when a supported Browser is detected. Otherwise, users will likely need to enter password and or Multifactor Authentication data (if multifactor authentication is configured on ADFS - not covered in this document) in order to authenticate with ADFS and log in to CloudBolt via SSO/SAML.

if ("Trident/7.0" -notin (Get-AdfsProperties | Select WIASupportedUserAgents -ExpandProperty WIASupportedUserAgents)) {

Set-AdfsProperties -WIASupportedUserAgents ((Get-ADFSProperties | Select -ExpandProperty WIASupportedUserAgents) + "Trident/7.0")

}
if ("Chrome" -notin (Get-AdfsProperties | Select WIASupportedUserAgents -ExpandProperty WIASupportedUserAgents)) {

Set-AdfsProperties -WIASupportedUserAgents ((Get-ADFSProperties | Select -ExpandProperty WIASupportedUserAgents) + "Chrome")

}

Step 13 - Create Active Directory Kerberos Host Service ServicePrincipalNames for the ADFS Server

Set-ADComputer "adfsserver" -ServicePrincipalNames @{Add='RestrictedKrbHost/adfsserver.somedomainname.com', 'RestrictedKrbHost/adfsserver'}

Step 14 - Set the ADFS Authentication Policy (removing Forms based authentication if present) for the Intranet

Set-AdfsGlobalAuthenticationPolicy -PrimaryIntranetAuthenticationProvider @('WindowsAuthentication', 'CertificateAuthentication')

Step 15 - Enable the IdpInitiatedSignonPage for ADFS

if ((Get-AdfsProperties).EnableIdpInitiatedSignonPage -eq $false) {

# Windows Server 2016 doesn't do this by default during installation
Set-AdfsProperties -EnableIdPInitiatedSignonPage $true

}

Step 16 - Reboot the ADFS Server

Step 17 - Validate/Start ADFS Server Service (if it is not already started)

if ((Get-WmiObject -Query "Select State From Win32_Service Where Name='adfssrv'").State -eq "Stopped") {

Write-Host "Starting ADFS Service"
Start-Service -Name "adfssrv"

}

Step 18 - Create the ADFS “Relying Party Trust” and the associated Claim Rules and Transforms

$claimrules =
@'
@RuleTemplate = "LdapClaims"
@RuleName = "LDAP Attributes"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”, Issuer == "AD AUTHORITY"]
=> issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname", "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn", "http://schemas.microsoft.com/ws/2008/06/identity/claims/role”), query = ";mail,sn,givenName,sAMAccountName,userPrincipalName,memberOf;{0}", param = c.Value);

# Note: When configuring CloudBolt’s SSO attribute names for the IdP, the whole url for email address and other property names would need to be sent as the attribute name… example: “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress

# the upn URL as shown above is likely what you want to set the username to in the SSO Attribute mappings in CloudBolt because it has the associated domain name for the user in that property (someuser@somedomainname.com) - your configuration/requirements may vary

@RuleTemplate = "MapClaims"
@RuleName = "Transform Claim"
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"]
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient");
'@

#The transient nameid-format above could be a different nameid-format, but needs to correspond to what you have configured in the CloudBolt SSO configuration page

#import the config from the metadata URL and set the transform rules – NOTE THE METADATA URL BELOW MUST BE REPLACED BY WHAT IS SHOWN IN THE CloudBolt SERVER’s SSO CONFIGURATION PAGE since there could be a different URL depending on your configuration and number of SSO providers

Add-ADFSRelyingPartyTrust -Name "cloudbolt.somedomainname.com" -MetadataURL "https://cloudbolt.somedomainname.com/authentication/saml2/1/metadata/" -IssuanceTransformRules $claimrules -AccessControlPolicyName "Permit Everyone"

Step 19 - Set the SamlResponseSignature to sign the message and assertion (optional)

Set-ADFSRelyingPartyTrust -TargetName "cloudbolt.somedomainname.com" -SamlResponseSignature "MessageAndAssertion"

Note: When deciding whether or not to sign the message and assertion or just the message only, the configuration inside CloudBolt changes because CloudBolt needs to know if the Message and/or Assertion are signed or not (Windows Server 2016 defaults to sign the “MessageOnly”)

Step 20 - Reboot the ADFS Server and validate the configuration in CloudBolt and ADFS communicate properly - Troubleshoot as necessary

At this point, the ADFS Server configuration should be completed, and as long as the CloudBolt server has been configured with corresponding information as to where to reach the IdP and what attribute names are configured, as well as signing and other configuration options are set correctly, everything should work correctly.

Here’s an example CloudBolt Configuration from the UI with the appropriate configuration for the way we setup ADFS above:

Note: Currently, the UI SSO integration does not support the “digest_algorithm” or “signing_algorithm” properties and as such CloudBolt only supports SHA-1 certificates presented from the ADFS server as a result.

As well, we do not support ADFS with the “Certificate Encrpytion” feature enabled in the OOTB UI SSO configuration.

Lastly, any version upgrades to the CloudBolt product will “downgrade” pysaml2 (if you have upgraded it) to the OOTB supported version, and you will need to re-upgrade pysaml2 to whatever version you want/need after the upgrade completes successfully (as shown above).

Have more questions? Submit a request

0 Comments

Please sign in to leave a comment.