-
Notifications
You must be signed in to change notification settings - Fork 199
Check Kerberos supported encryption types in Auth Debug script #297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5de997a
8d91b27
ed7b75d
dad5a6c
d2be294
cf555dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3310,6 +3310,9 @@ function Debug-KerberosTicketEncryption | |
| $kerberosTicketEncryptionClient = $kerberosTicketEncryptionClient.Value.ToString().replace(' ', '') -split ',' | ||
| } | ||
|
|
||
| $registrySupportedEncryptionTypes = (Get-ClientSupportedEncryptionTypes).EncryptionTypes | ||
| $registrySupportedEncryptionTypes = $registrySupportedEncryptionTypes | ForEach-Object { $_ -replace '-', '' } | ||
| $kerberosTicketEncryptionClient = $registrySupportedEncryptionTypes | Where-Object { $kerberosTicketEncryptionClient -contains $_ } | ||
|
|
||
| $kerberosTicketEncryptionServer = $protocolSettings.KerberosTicketEncryption | ||
| if($null -eq $kerberosTicketEncryptionServer) | ||
|
|
@@ -3340,6 +3343,166 @@ function Debug-KerberosTicketEncryption | |
| } | ||
| } | ||
|
|
||
| function Get-ClientSupportedEncryptionTypes { | ||
| <# | ||
| .SYNOPSIS | ||
| Get the Kerberos supported encryption types enabled on the client machine from the Windows registry. | ||
|
|
||
| .DESCRIPTION | ||
| This cmdlet reads the SupportedEncryptionTypes registry value from the Kerberos Parameters key | ||
| and decodes it into human-readable encryption type names. The registry key is located at: | ||
| HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters\SupportedEncryptionTypes | ||
|
|
||
| The value is a DWORD bitmask where: | ||
| - Bit 0 (0x1): DES-CBC-CRC | ||
| - Bit 1 (0x2): DES-CBC-MD5 | ||
| - Bit 2 (0x4): RC4-HMAC | ||
| - Bit 3 (0x8): AES128-CTS-HMAC-SHA1-96 (AES-128) | ||
| - Bit 4 (0x10): AES256-CTS-HMAC-SHA1-96 (AES-256) | ||
|
|
||
| If the registry key doesn't exist, Windows defaults to RC4-HMAC and AES encryption types. | ||
|
|
||
| .OUTPUTS | ||
| PSCustomObject with the following properties: | ||
| - RawValue: The raw DWORD value from registry (or $null if not set) | ||
| - EncryptionTypes: Array of encryption type names enabled | ||
| - SupportsAES256: Boolean indicating if AES-256 is supported | ||
| - SupportsAES128: Boolean indicating if AES-128 is supported | ||
| - SupportsRC4: Boolean indicating if RC4-HMAC is supported | ||
|
|
||
| .EXAMPLE | ||
| PS> Get-ClientSupportedEncryptionTypes | ||
|
|
||
| RawValue : 28 | ||
| EncryptionTypes : {RC4-HMAC, AES-128, AES-256} | ||
| SupportsAES256 : True | ||
| SupportsAES128 : True | ||
| SupportsRC4 : True | ||
| #> | ||
|
|
||
| [CmdletBinding()] | ||
| param() | ||
|
|
||
| process { | ||
| Assert-IsWindows | ||
|
|
||
| $registryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Kerberos\Parameters" | ||
| $registryValueName = "SupportedEncryptionTypes" | ||
|
|
||
| # Encryption type flags as defined by Microsoft | ||
| $encryptionTypeFlags = @{ | ||
| 0x1 = "DES-CBC-CRC" | ||
| 0x2 = "DES-CBC-MD5" | ||
| 0x4 = "RC4-HMAC" | ||
| 0x8 = "AES-128" | ||
| 0x10 = "AES-256" | ||
| } | ||
|
|
||
| $rawValue = $null | ||
| $encryptionTypes = @() | ||
|
|
||
| Write-Verbose "Registry Path: $registryPath" | ||
| Write-Verbose "Registry Value Name: $registryValueName" | ||
| $regValue = Get-ItemProperty -Path $registryPath -Name $registryValueName -ErrorAction SilentlyContinue | ||
|
|
||
| if ($null -ne $regValue -and $null -ne $regValue.$registryValueName) { | ||
| $rawValue = $regValue.$registryValueName | ||
|
|
||
| # Decode the bitmask | ||
| foreach ($flag in $encryptionTypeFlags.Keys) { | ||
| if (($rawValue -band $flag) -eq $flag) { | ||
| $encryptionTypes += $encryptionTypeFlags[$flag] | ||
| } | ||
| } | ||
|
|
||
| Write-Verbose "Raw Value: $($rawValue) (0x$($rawValue.ToString('X')))" | ||
| Write-Verbose "Supported Types: $($encryptionTypes -join ', ')" | ||
| } else { | ||
| # Registry key not set - Windows defaults to RC4-HMAC, AES-128, and AES-256 | ||
| Write-Verbose "SupportedEncryptionTypes registry value not found. Using Windows defaults (RC4-HMAC, AES-128, AES-256)." | ||
| $encryptionTypes = @("RC4-HMAC", "AES-128", "AES-256") | ||
| } | ||
|
|
||
| return [PSCustomObject]@{ | ||
| RawValue = $rawValue | ||
| EncryptionTypes = $encryptionTypes | ||
| SupportsAES256 = $encryptionTypes -contains "AES-256" | ||
| SupportsAES128 = $encryptionTypes -contains "AES-128" | ||
| SupportsRC4 = $encryptionTypes -contains "RC4-HMAC" | ||
| } | ||
| } | ||
| } | ||
|
|
||
| function Get-ServerSupportedEncryptionTypes { | ||
| <# | ||
| .SYNOPSIS | ||
| Get the supported Authentication Methods and Kerberos supported encryption types enabled on storage account. | ||
|
|
||
| .DESCRIPTION | ||
| This cmdlet retrieves the supported Authentication Methods and Kerberos encryption types for a storage account. | ||
|
|
||
| .OUTPUTS | ||
| PSCustomObject with the following properties: | ||
| - AuthenticationMethods : Array of authentication methods supported | ||
| - SupportsKerberos : Boolean indicating if Kerberos is supported | ||
| - SupportsNTLMv2 : Boolean indicating if NTLMv2 is supported | ||
| - EncryptionTypes: Array of encryption type names enabled | ||
| - SupportsAES256: Boolean indicating if AES-256 is supported | ||
| - SupportsRC4: Boolean indicating if RC4-HMAC is supported | ||
|
|
||
| .EXAMPLE | ||
| PS> Get-ServerSupportedEncryptionTypes -StorageAccountName "mystorageaccount" -ResourceGroupName "myresourcegroup" | ||
|
|
||
| AuthenticationMethods : {Kerberos} | ||
| SupportsKerberos : True | ||
| SupportsNTLMv2 : False | ||
| EncryptionTypes : {RC4-HMAC, AES-128, AES-256} | ||
| SupportsAES256 : True | ||
| SupportsRC4 : True | ||
| #> | ||
|
|
||
| [CmdletBinding()] | ||
| param ( | ||
| [Parameter(Mandatory=$True, Position=0, HelpMessage="Storage account name")] | ||
| [string]$StorageAccountName, | ||
|
|
||
| [Parameter(Mandatory=$True, Position=1, HelpMessage="Resource group name")] | ||
| [string]$ResourceGroupName | ||
| ) | ||
|
|
||
| process { | ||
| $storageAccount = Validate-StorageAccount -ResourceGroupName $ResourceGroupName ` | ||
| -StorageAccountName $StorageAccountName -ErrorAction Stop | ||
|
|
||
| $protocolSettings = (Get-AzStorageFileServiceProperty -StorageAccount $storageAccount -ErrorAction Stop).ProtocolSettings.Smb | ||
|
|
||
| $authenticationMethods = $protocolSettings.AuthenticationMethods | ||
| if ($null -eq $authenticationMethods) | ||
| { | ||
| Write-Verbose "Authentication methods are not set on the storage account. Default all types are supported." | ||
| $authenticationMethods = "NTLMv2", "Kerberos" | ||
| } | ||
| Write-Verbose "Authentication Methods supported on the server side: $($authenticationMethods -join ', ')" | ||
|
|
||
| $kerberosTicketEncryptionServer = $protocolSettings.KerberosTicketEncryption | ||
| if($null -eq $kerberosTicketEncryptionServer) | ||
| { | ||
| Write-Verbose "Kerberos Ticket Encryption is not set on the storage account. Default all types are supported." | ||
| $kerberosTicketEncryptionServer = "RC4-HMAC", "AES-256" # null(default): all values are accepted on the server | ||
| } | ||
| Write-Verbose "Kerberos Ticket Encryption Types supported on the server side: $($kerberosTicketEncryptionServer -join ', ')" | ||
|
|
||
| return [PSCustomObject]@{ | ||
| AuthenticationMethods = $authenticationMethods | ||
| SupportsKerberos = $authenticationMethods -contains "Kerberos" | ||
| SupportsNTLMv2 = $authenticationMethods -contains "NTLMv2" | ||
| EncryptionTypes = $kerberosTicketEncryptionServer | ||
| SupportsAES256 = $kerberosTicketEncryptionServer -contains "AES-256" | ||
| SupportsRC4 = $kerberosTicketEncryptionServer -contains "RC4-HMAC" | ||
| } | ||
| } | ||
| } | ||
|
|
||
| function Debug-ChannelEncryption | ||
| { | ||
| [CmdletBinding()] | ||
|
|
@@ -3657,6 +3820,8 @@ function Debug-AzStorageAccountEntraKerbAuth { | |
| "CheckIpHlpScv" = [CheckResult]::new("CheckIpHlpScv"); | ||
| "CheckFiddlerProxy" = [CheckResult]::new("CheckFiddlerProxy"); | ||
| "CheckEntraJoinType" = [CheckResult]::new("CheckEntraJoinType") | ||
| "CheckClientSupportedEncryptionTypes" = [CheckResult]::new("CheckClientSupportedEncryptionTypes"); | ||
| "CheckServerSupportedEncryptionTypes" = [CheckResult]::new("CheckServerSupportedEncryptionTypes"); | ||
| } | ||
| # | ||
| # Port 445 check | ||
|
|
@@ -4055,6 +4220,76 @@ function Debug-AzStorageAccountEntraKerbAuth { | |
| $checks["CheckEntraJoinType"].Issue = $_ | ||
| } | ||
| } | ||
|
|
||
| # | ||
| # Check Client Supported Encryption Types | ||
| # | ||
|
|
||
| if (!$filterIsPresent -or $Filter -match "CheckClientSupportedEncryptionTypes") | ||
| { | ||
| try { | ||
| $checksExecuted += 1; | ||
| Write-Host "Checking Client Supported Encryption Types" | ||
|
|
||
| $clientEncryption = Get-ClientSupportedEncryptionTypes | ||
|
|
||
| if ($clientEncryption.SupportsAES256) { | ||
| $checks["CheckClientSupportedEncryptionTypes"].Result = "Passed" | ||
| Write-TestingPassed | ||
| } | ||
| else { | ||
| $message = "Entra Kerberos requires AES256 encryption to be enabled." ` | ||
| + " To enable AES256 encryption, open Local Group Policy Editor and edit the following policy:" ` | ||
| + " '$($PSStyle.Foreground.BrightCyan)Computer Configuration -> Windows Settings -> Security Settings -> Local Policies -> Security Options -> Network security: Configure encryption types allowed for Kerberos$($PSStyle.Reset)'" ` | ||
| + " and ensure that 'AES256_HMAC_SHA1' is checked." | ||
|
|
||
| $checks["CheckClientSupportedEncryptionTypes"].Result = "Failed" | ||
| $checks["CheckClientSupportedEncryptionTypes"].Issue = "AES256 encryption type is not enabled." | ||
| Write-TestingFailed -Message $message | ||
| } | ||
| } catch { | ||
| $checks["CheckClientSupportedEncryptionTypes"].Result = "Failed" | ||
| $checks["CheckClientSupportedEncryptionTypes"].Issue = $_ | ||
| Write-TestingFailed -Message $_ | ||
| } | ||
| } | ||
|
|
||
| # | ||
| # Check Server Supported Encryption Types | ||
| # | ||
|
|
||
| if (!$filterIsPresent -or $Filter -match "CheckServerSupportedEncryptionTypes") | ||
| { | ||
| try { | ||
| $checksExecuted += 1; | ||
| Write-Host "Checking Server Supported Encryption Types" | ||
|
|
||
| $serverEncryption = Get-ServerSupportedEncryptionTypes -StorageAccountName $StorageAccountName -ResourceGroupName $ResourceGroupName | ||
|
|
||
| if ($serverEncryption.SupportsKerberos -and $serverEncryption.SupportsAES256) { | ||
| $checks["CheckServerSupportedEncryptionTypes"].Result = "Passed" | ||
| Write-TestingPassed | ||
| } | ||
| else { | ||
| $disabledConfiguration = (-not $serverEncryption.SupportsKerberos) ? "Kerberos Authentication" : "AES-256 encryption" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we print both if both are required? Haven't tested the code below, but something like this: $disabledConfiguration = @()
if (-not $serverEncryption.SupportsKerberos) { $disabledConfiguration += "Kerberos authentication" }
if (-not $serverEncryption.SupportsAES256) { $disabledConfiguration += "AES-256 encryption" }
$message = "Entra Kerberos requires $($disabledConfiguration -join ", ") to be enabled on the storage account"
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems that when Kerberos is disabled (at least through the portal) it also disables all the encryption types. So I kept the same message but added a reminder to enable AES-256 when enabling Kerberos in the case Kerberos is disabled |
||
|
|
||
| $message = "Entra Kerberos requires $disabledConfiguration to be enabled on the storage account." | ||
| if (-not $serverEncryption.SupportsKerberos) { | ||
| $message += " When enabling Kerberos Authentication, make sure to also enable AES-256 encryption." | ||
| } | ||
|
|
||
| $checks["CheckServerSupportedEncryptionTypes"].Result = "Failed" | ||
| $checks["CheckServerSupportedEncryptionTypes"].Issue = "$disabledConfiguration is not enabled." | ||
| Write-TestingFailed -Message $message | ||
| } | ||
| } catch { | ||
| $checks["CheckServerSupportedEncryptionTypes"].Result = "Failed" | ||
| $checks["CheckServerSupportedEncryptionTypes"].Issue = $_ | ||
| Write-TestingFailed -Message $_ | ||
| } | ||
| } | ||
|
|
||
|
|
||
| SummaryOfChecks -checks $checks -filterIsPresent $filterIsPresent -checksExecuted $checksExecuted | ||
| } | ||
| } | ||
|
|
@@ -4311,7 +4546,6 @@ function Debug-EntraKerbAdminConsent { | |
| } | ||
| } | ||
|
|
||
|
|
||
| function Debug-AzStorageAccountADDSAuth { | ||
| <# | ||
| .SYNOPSIS | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.