Automatically Roll Over Kerberos Decryption Key with AAD Seamless Single Sign-On
When it comes to Azure, Azure Active Directory is usually one of the easiest services to spin up quickly. Overall, integration into the IAM world of Azure is usually a fast path if a customer adopts Microsoft 365 (formerly Office 365). Even before I became full-time Azure, I spent quite a bit of time in Azure Active Directory and Microsoft 365 performing a number of Exchange Online mailbox migrations. But I digress a bit here...
There are a number of ways to synchronize identities + federate (if you so choose). Having supported quite a number of environments over the years that didn't work correctly related to ADFS (Active Directory Federated Services), I became excited to test out Pass Through Authentication a number of years back. Azure Active Directory (Azure AD) Pass-through Authentication allows users to sign in to both on-premises and cloud-based applications by using the same passwords. Pass-through Authentication signs users in by validating passwords directly against an on-premises Active Directory environment. Sounds a lot like ADFS, right? You're right, except 1 big difference: the infrastructure to support ADFS is vast and resides on-premises. Pass Through Authentication only requires a few agents on-premises to validate the authentication/authorization pattern.
I was sold. I wasn't interested in messing with my "on-premises" lab and I've worked with customers to get them confident that Pass Through Authentication could work for them. Not the big customers though, as they were usually pretty content with ADFS or a 3rd party competitor like Ping or Okta.
As a byproduct of configuring Pass Through Authentication, I dug deep into Azure Active Directory Seamless Single Sign-On. I know the trend is to Azure AD join, Azure AD register, or Hybrid Azure AD join all devices these days, but it's not exactly easy with the way I run my home environment. Yes, I'm the nerd that's still rolling her own domain controllers in a single forest, single domain configuration at home. Most of my machines (servers) are already joined to my domain and Group Policy Objects are applied. That was a labor of love over the last 12 years (yeah my home domain is 12 years old this year), so I'm not going to redo that too much unless I 100% need to. I generally like taking the path of least resistance for everything I build at home (especially after that deep dive into Group Policy back in like 2009 when I was still pretty new to Active Directory/Group Policy administration). Azure AD Seamless SSO automatically signs users in when they are on corporate devices connected to a corporate network. When enabled, users don't need to type in their passwords to sign in to Azure AD. This feature provides users with easy access to cloud-based applications without needing any additional on-premises components deployed for authorization.
Something I learned though is that there's a recommendation of rolling over the Kerberos key for the Azure AD Connect SSO computer account every 30 days. When Seamless SSO is enabled, there's a computer account that gets created on-premises (AZUREADSSO) for each forest that is synchronized to Azure AD using Azure AD Connect. At one point, it was thought that rolling over the decryption key would automagically just happen within the software, however after recently upgrading my Azure Active Directory Connect server, I noticed the following icon when checking on my AD Connect blade within the portal:
If you hover over the warning icon, the following text displays:
Digging into the documentation, you might find the following FAQ of how to roll over the Kerberos decryption key of the AZUREADSSO computer account. Seems straightforward and something you could potentially automate, right? I don't know if you're like me, but a task that leans on PowerShell and needs to run on a schedule is a prime candidate for automation.
There are some interesting things I found out through experimentation (and this might not work with your environment as a result):
1) The account that runs the PowerShell script on-premises needs to either be a domain administrator or a Hybrid Identity Administrator. The account that runs the PowerShell script against Azure Active Directory needs to be a Global Administrator in your Azure AD tenant. If you want to read the actual documentation, please refer to this article.
2) The account on-premises needs to have rights to log on as a batch job on the AAD Connect server. The link I am supplying should help you configure that for your environment. Note, you can also configure this via Group Policy. Basically whatever is easiest for your environment. If you configure this setting via Group Policy, you may need to force a GPO update on the AAD Connect server.
3) The Global Administrator account either needs 2FA turned off or you need an app password for the task. Makes sense, right? You're establishing a remote PowerShell session with Azure AD on a schedule and you wouldn't be able to answer a password challenge from Microsoft Authenticator.
Those two pieces aside, I personally feel automation is still ideal as it would save your engineers the hassle of running a script once a month on a schedule. If anything I've covered thus far makes you feel this would not be a good solution for your environment, take the script talked about above in the FAQ link and run it on a monthly schedule to roll the Kerberos decryption key of the AZUREADSSO computer account.
Now, onto the interesting stuff!
I recently blogged about the PowerShell cmdlet ConvertFrom-SecureString. ConvertFrom-SecureString is a prime candidate to use here to store an encrypted standard credential in a text file. You'll first run the following script to save credentials locally for use within the automation task that rolls over the Kerberos decryption key:
$onPrem = Get-Credential $onPrem.Password | ConvertFrom-SecureString | Set-Content C:\Scripts\onPrem_Encrypted_Password.txt $azureAd = Get-Credential $azureAd.Password | ConvertFrom-SecureString | Set-Content C:\Scripts\azureAd_Encrypted_Password.txt
From there, there's a little bit of tooling you'll need to do with an additional script that will be run on a schedule. Take note of the following script:
$CloudUser = '[email protected]' $CloudEncrypted = Get-Content "C:\Scripts\azureAd_Encrypted_Password.txt"` | ConvertTo-SecureString $CloudCred = New-Object ` System.Management.Automation.PsCredential($CloudUser,$CloudEncrypted) $OnpremUser = 'DOMAIN\USERNAME' $OnpremEncrypted = Get-Content "C:\Scripts\onPrem_Encrypted_Password.txt"` | ConvertTo-SecureString $OnpremCred = New-Object ` System.Management.Automation.PsCredential($OnpremUser,$OnpremEncrypted) Import-Module 'C:\Program Files\Microsoft Azure Active Directory Connect\AzureADSSO.psd1' New-AzureADSSOAuthenticationContext -CloudCredentials $CloudCred Update-AzureADSSOForest -OnPremCredentials $OnpremCred
If the above script is a little awkward to read or copy/paste, you can always grab this script from my GitHub account.
Ok in the order of completion thus far, you've converted a secure string password to an encrypted standard string that you can use in conjunction with Task Scheduler within Windows AND you've managed to grab the script required to roll over the Kerberos decryption key. Now...it's onto the Task Scheduler configuration.
Load up Task Scheduler within your Azure AD Connect server. On the far right, under Actions, select Create Basic Task...
Give the task a name. I created a task with the following name:
After you've provided a name, select Next >. This task needs to run once a month. Select Monthly and then select Next >.
Select all months in the drop down and start the task at a time that makes the most sense for your environment. I selected that the task will run on the 15th of each month at midnight. After you've configured everything on this screen, select Next >.
On the Action screen, select Start a program, and select Next >.
On the Start a Program screen, input Powershell.exe in the Program/script field. For the Add arguments field, type in the following:
Note, place the location of your script that you generated above in the double quotation marks. Also, type in C:\Scripts\ in the Start in (optional): field. Then select Next >.
On the Finish screen, select Finish.
As I was building this post for my blog, it dawned upon me that I never specified to have the task be run whether my account was logged in or not. Turns out the Create Task task is probably what you might want to use vs. the Create Basic Task going forward. Since you've been following me up to this point, head over to your Task Scheduler Library and locate the scheduled task. Right click on the task and select Properties.
On the General tab, ensure you have Run whether user is logged on or not selected, plus Run with highest privileges. Leave Do not store password. The task will only have access to local computer resources unchecked. After everything has been configured, select OK.
You will be prompted for the account's credentials. Input that information and select OK.
That's it! Your task has been officially scheduled to run at a date in the near future. You can either run it now or wait for the task to run. Because I'm a bit of a control freak, I decided to run this on my new AAD Connect server (with updated TLS 1.2 configs). You run the task by right clicking on the task and selecting run. Once complete, you will see a result message like what is shown below:
Then, when you head to the Azure portal, notice how the warning triangle is missing:
You've now successfully configured an automated task that runs via Task Scheduler, uses a local PowerShell script on the AAD Connect server, and rolls that Kerberos decryption key all the way over for the AZUREADSSO account. Woo!
If you would like to clone my GitHub repo or take the code, point your browser here.
Hopefully this helps you out! I liked setting this up as it leaned on a lot of different technologies and now I don't have to worry about my Kerberos decryption key being rotated on a monthly basis.