Security troubleshooting

 

Applies To: Windows Azure Pack

This topic describes troubleshooting issues that pertains to security and authentication in Windows Azure Pack for Windows Server. Many issues can be resolved by reviewing the Credentials checklist in this topic. Recommendations are provided for the following issues:

  • After integrating AD FS, reset the management portal to use AD

  • After integrating AD FS, cannot access the tenant portal

  • Get a token with the Get-MgmtSvcToken cmdlet

  • Programmatically use tenant certificates

  • Replace a self-signed certificate with a trusted certificate

  • Resolve certificate warnings

  • Sign in to the management portal from multiple accounts

  • Review SSL/TLS settings

Credentials checklist

The following checklist provides best practices for configuring certificates, user names, and passwords for Windows Azure Pack and the products and providers it uses.

  • For testing or non-internet-facing components like the management portal for administrators or Admin API, you can use the Microsoft certification authority to create self-signed certificates.

  • For Internet-facing components such as the management portal for tenants and the Tenant Public API, use a trusted public certification authority.

  • Configure the Application Pool identities for Service Provider Foundation in Internet Information Services (IIS) on the server running Service Provider Foundation so that they use the domain user credentials account. Using Network Services is not recommended.

  • Configure the Application Pool identities on the servers running System Center 2012 R2 Virtual Machine Manager and Service Provider Foundation to use the same domain account that has Logon as a service rights.

  • Configure Service Provider Foundation to use basic authentication in IIS.

  • Configure a local user account that has Administrative rights to be a member of the VMM, Admin, Provider, and Usage groups on the server running Service Provider Foundation. Use this local user account to register the Service Provider Foundation endpoint with Windows Azure Pack for Windows Server.

For more information, see the blog post Troubleshooting Windows Azure Pack, Service Provider Foundation & Virtual Machine Manager. For an overview of the Service Provider Foundation web services, see Manage Web Services and Connections in Service Provider Foundation. See also Windows Azure Pack Authentication Overview.

After integrating AD FS, cannot access the tenant portal

Pertains to: Configure Active Directory Federation Services for Windows Azure Pack

Issue

The tenant logon screen is not displayed after configuring AD FS (Active Directory Federation Services) or cannot access management portal for tenants.

Recommendation

After you integrate AD FS in the domain where Windows Azure Pack is installed, the login page is bypassed going directly to the portal. This is the expected browser behavior.

If you cannot access the management portal for tenants, use Server Manager to run ADSI Edit and verify that your AD SF server has a Service Principal Name (SPN) is listed. The SPN should be in the form of http/myADFSServer.

Back to top

After integrating AD FS, reset the management portal to use AD

Pertains to: Configure Active Directory Federation Services for Windows Azure Pack

Issue

Want to return to using Active Directory (AD) for the management portal, after integrating Active Directory Federation Services (AD FS).

Recommendation

You must reestablish trust between the management portal for administrators and the Windows authentication site as you did for AD FS. The Windows authentication site is port 30072. You can use the Windows PowerShell cmdlets Set-MgmtSvcRelyingPartySettigns and Set-MgmtSvcIdentityProviderSettings.

Get a token with the Get-MgmtSvcToken cmdlet

Pertains to: Windows Azure Pack for Windows Server Automation with Windows PowerShell

Issue

The Get-MgmtSvcToken does not return the token as expected.

Recommendation

This could be an issue with the Get-MgmtSvcToken cmdlet not using Active Directory Federation Services (AD FS) correctly. The following script defines a function, Get-AdfsToken, as a workaround.

function Get-AdfsToken([string]$adfsAddress, [PSCredential]$credential)
{
    $clientRealm = 'http://azureservices/AdminSite'
    $allowSelfSignCertificates = $true

    Add-Type -AssemblyName 'System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
    Add-Type -AssemblyName 'System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'

    $identityProviderEndpoint = New-Object -TypeName System.ServiceModel.EndpointAddress -ArgumentList ($adfsAddress + '/adfs/services/trust/13/usernamemixed')
    $identityProviderBinding = New-Object -TypeName System.ServiceModel.WS2007HttpBinding -ArgumentList ([System.ServiceModel.SecurityMode]::TransportWithMessageCredential)
    $identityProviderBinding.Security.Message.EstablishSecurityContext = $false
    $identityProviderBinding.Security.Message.ClientCredentialType = 'UserName'
    $identityProviderBinding.Security.Transport.ClientCredentialType = 'None'

    $trustChannelFactory = New-Object -TypeName System.ServiceModel.Security.WSTrustChannelFactory -ArgumentList $identityProviderBinding, $identityProviderEndpoint
    $trustChannelFactory.TrustVersion = [System.ServiceModel.Security.TrustVersion]::WSTrust13

    if ($allowSelfSignCertificates)
    {
        $certificateAuthentication = New-Object -TypeName System.ServiceModel.Security.X509ServiceCertificateAuthentication
        $certificateAuthentication.CertificateValidationMode = 'None'
        $trustChannelFactory.Credentials.ServiceCertificate.SslCertificateAuthentication = $certificateAuthentication
    }

    $ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($credential.Password)
    $password = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr)
    [System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($ptr)

    $trustChannelFactory.Credentials.SupportInteractive = $false
    $trustChannelFactory.Credentials.UserName.UserName = $credential.UserName
    $trustChannelFactory.Credentials.UserName.Password = $password #$credential.Password

    $rst = New-Object -TypeName System.IdentityModel.Protocols.WSTrust.RequestSecurityToken -ArgumentList ([System.IdentityModel.Protocols.WSTrust.RequestTypes]::Issue)
    $rst.AppliesTo = New-Object -TypeName System.IdentityModel.Protocols.WSTrust.EndpointReference -ArgumentList $clientRealm
    $rst.TokenType = 'urn:ietf:params:oauth:token-type:jwt'
    $rst.KeyType = [System.IdentityModel.Protocols.WSTrust.KeyTypes]::Bearer

    $rstr = New-Object -TypeName System.IdentityModel.Protocols.WSTrust.RequestSecurityTokenResponse

    $channel = $trustChannelFactory.CreateChannel()
    $token = $channel.Issue($rst, [ref] $rstr)

    $tokenString = ([System.IdentityModel.Tokens.GenericXmlSecurityToken]$token).TokenXml.InnerText;
    $result = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($tokenString))
    return $result
}

# Fill in values
$adfsAddress = 'https://adfshost'
$username = 'domain\username'
$password = 'password'
$securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$securePassword

$token = Get-AdfsToken -adfsAddress $adfsAddress -credential $credential 
$token

Back to top

Programmatically use tenant certificates

Pertains to: Service Provider Foundation Developer's Guide

Issue

You need to create a certificate and upload it to the management portal for tenants and then be able to programmatically use it.

Recommendation

Use the following procedure:

  1. Create a certificate (it can be self-signed). It should have a .cer file extension.

  2. On the My Account page of the management portal for tenants, click Management Certificates.

  3. Pass the certificate in the header of the request to the Tenant Public API for authentication, as shown in the following example.

    Note

    You will be able to access only the subscription that this certificate is assigned to. You will not be able to delete the subscription through the Tenant Public API.

    X509Certificate2 mycert3 = new X509Certificate2("C:\\WorkDocs\\Test\\Management Certs\\myCert.cer");
    HttpClient httpClient = new HttpClient();
    var handler = new WebRequestHandler();
    handler.ClientCertificates.Add(mycert3);
    handler.PreAuthenticate = true;
    httpClient = new HttpClient(handler);
    
    string tenantPublicEndpoint = "https://test.fabrikam.com:30006/";
    string subscriptionid = " 7d31eb89-bb1e-4b16-aa3c-993f978b6bc1";
    
    string subscriptionEndpoint = tenantPublicEndpoint + subscriptionid+ "/services/webspaces/defaultwebspace/sites";
    var response = httpClient.GetAsync(subscriptionEndpoint);
    var resultsStr = response.Result.Content.ReadAsStringAsync().Result;
    

Back to top

Replace a self-signed certificate with a trusted certificate

Pertains to: Administer Windows Azure Pack for Windows Server

Issue

After you use a self-signed certificate for a test environment, you want to replace the certificate with one that is issued from a trusted authority.

Recommendation

Install the certificate in the Personal Store of the local computer and map the certificate to each web site in Internet Information Services (IIS) Manager. The certificate should meet the following requirements:

  • Come from a trusted certification authority

  • Have a valid date range

  • Provide a valid usage and intended purpose statement

  • Provide server authentication

  • Match the domain name of the certificate with the name of the web site

  • Have an RSA-1024-bit encryption or higher

  • Include the private key

Back to top

Resolve certificate warnings

Pertains to: Deploy Windows Azure Pack for Windows Server

Issue

Certificate warnings persist with certificate from a trusted authority.

Recommendation

Some browsers do not process the Authority Information Access field that is in the certificate during certificate validation. The workaround is to explicitly install the intermediate certificates in the certificate store. For a list of certification authorities that support this field, see Windows and Windows Phone 8 SSL Root Certificate Program (Member CAs).

Back to top

Review SSL/TLS settings

Pertains to: Deploy Windows Azure Pack for Windows Server

Issue

Weak communication security may result in a flood of Schannel errors showing up in the system event log.

Recommendation

To improve the security of Windows Azure Pack communication channels, consider updating your SSL/TLS settings. Before implementing these changes, you should ensure they don’t impact other applications or services.

You can run the following script on each machine running Windows Azure Pack to make these changes for you:

# PowerShell script to secure TLS/SSL settings.
# Copyright (c) Microsoft Corporation. All rights reserved.
# 20-Jun-2015 Update-ComputerSchannelSettings.ps1

<#
.Synopsis
   Apply HTTP.SYS settings
.NOTES
   Reference: Http.sys registry settings for Windows
   https://support.microsoft.com/en-us/kb/820129
#>
function Set-HttpSysSettings()
{
    Write-Verbose -Message "$($Myinvocation.MyCommand.Name)" -Verbose

    $regPath = "HKLM:\System\CurrentControlSet\Services\HTTP\Parameters"

    # Read original values.
    $maxFieldLength = (Get-ItemProperty -Path $regPath -Name MaxFieldLength -ErrorAction SilentlyContinue).MaxFieldLength
    $maxRequestBytes = (Get-ItemProperty -Path $regPath -Name MaxRequestBytes -ErrorAction SilentlyContinue).MaxRequestBytes
    Write-Verbose -Message "HTTP.SYS settings:`r`n  MaxFieldLength = $maxFieldLength`r`n  MaxRequestBytes = $maxRequestBytes" -Verbose

    # Is update needed?
    if ($maxFieldLength -ne 32KB -or $maxRequestBytes -ne 32KB)
    {
        # Write updated values.
        Set-ItemProperty -Path $regPath -Name MaxFieldLength -Value 32KB
        Set-ItemProperty -Path $regPath -Name MaxRequestBytes -Value 32KB

        # Read updated values.
        $maxFieldLength = (Get-ItemProperty -Path $regPath -Name MaxFieldLength).MaxFieldLength
        $maxRequestBytes = (Get-ItemProperty -Path $regPath -Name MaxRequestBytes).MaxRequestBytes
        Write-Verbose -Message "HTTP.SYS settings (updated):`r`n  MaxFieldLength = $maxFieldLength`r`n  MaxRequestBytes = $maxRequestBytes" -Verbose

        # Changes that are made to the registry will not take effect until you restart the HTTP service.
        Write-Warning -Message "HTTP.SYS settings updated; restarting the HTTP service."
        Restart-Service -Name "http" -Force -Verbose
    }

    return $false # No reboot needed.
}

<#
.Synopsis
   Apply SSL configuration settings (TLS Cipher Suite Ordering)
.NOTES
   Reference: Prioritizing Schannel Cipher Suites
   https://msdn.microsoft.com/en-us/library/windows/desktop/bb870930(v=vs.85).aspx
#>
function Set-SchannelCipherOrder()
{
    Write-Verbose -Message "$($Myinvocation.MyCommand.Name)" -Verbose
    $reboot = $false

    $regPath = "HKLM:\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002"

    # The ordered suites names need to be specified as a single string (REG_SZ)
    # with each suite separated by commas and with no embedded spaces.
    # The list of cipher suites is limited to 1023 characters.
    $cipherOrder = @(
        'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384'
        'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256'
        'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384'
        'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256'
        'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384'
        'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256'
        'TLS_RSA_WITH_AES_256_GCM_SHA384'
        'TLS_RSA_WITH_AES_128_GCM_SHA256'
        'TLS_RSA_WITH_AES_256_CBC_SHA256'
        'TLS_RSA_WITH_AES_128_CBC_SHA256'
        'TLS_RSA_WITH_AES_256_CBC_SHA'
        'TLS_RSA_WITH_AES_128_CBC_SHA'
    )
    $cipherOrderList = ($cipherOrder -join ',')

    # Read original values.
    $functions = (Get-ItemProperty -Path $regPath -Name Functions -ErrorAction SilentlyContinue).Functions
    Write-Verbose -Message "Schannel Cipher Order:`r`n  Functions = $($functions -split ',' | ConvertTo-Json)" -Verbose

    # Is update needed?
    if ($functions -ne ($cipherOrder -join ','))
    {
        # Write updated values.
        Set-ItemProperty -Path $regPath -Name Functions -Value $cipherOrderList -Force

        # Read updated values.
        $functions = (Get-ItemProperty -Path $regPath -Name Functions -ErrorAction SilentlyContinue).Functions
        Write-Verbose -Message "Schannel Cipher Order (updated):`r`n  Functions = $($functions -split ',' | ConvertTo-Json)" -Verbose

        # It is necessary to restart the computer after modifying this setting for the changes to take effect.
        Write-Warning -Message "Schannel Cipher Order updated; it is necessary to restart the computer."
        $reboot = $true ### TODO: Restart-Computer -Force -Verbose
    }

    return $reboot
}
<#
.Synopsis
   Apply TLS Protocol version configuration
.NOTES
   Reference: How to Disable SSL 3.0 in Azure Websites, Roles, and Virtual Machines
   https://azure.microsoft.com/blog/2014/10/19/how-to-disable-ssl-3-0-in-azure-websites-roles-and-virtual-machines/
#>
function Set-SchannelProtocols()
{
    Write-Verbose -Message "$($Myinvocation.MyCommand.Name)" -Verbose
    $reboot = $false

    $regPath = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols"
    $protocolSettings = @(
        [PSCustomObject]@{ Path = "$regPath\SSL 2.0\Client"; Name = "Enabled"; Value = 0 }
        [PSCustomObject]@{ Path = "$regPath\SSL 2.0\Server"; Name = "Enabled"; Value = 0 }
        [PSCustomObject]@{ Path = "$regPath\SSL 3.0\Client"; Name = "Enabled"; Value = 0 }
        [PSCustomObject]@{ Path = "$regPath\SSL 3.0\Server"; Name = "Enabled"; Value = 0 }
        [PSCustomObject]@{ Path = "$regPath\TLS 1.0\Client"; Name = "Enabled"; Value = 1 }
        [PSCustomObject]@{ Path = "$regPath\TLS 1.0\Server"; Name = "Enabled"; Value = 1 }
        [PSCustomObject]@{ Path = "$regPath\TLS 1.1\Client"; Name = "Enabled"; Value = 1 }
        [PSCustomObject]@{ Path = "$regPath\TLS 1.1\Server"; Name = "Enabled"; Value = 1 }
        [PSCustomObject]@{ Path = "$regPath\TLS 1.2\Client"; Name = "Enabled"; Value = 1 }
        [PSCustomObject]@{ Path = "$regPath\TLS 1.2\Server"; Name = "Enabled"; Value = 1 }
    )

    # Read original values.
    $currentProtocolSettings = @()
    foreach ($protocolSetting in $protocolSettings)
    {
        $value = (Get-ItemProperty -Path $protocolSetting.Path -Name $protocolSetting.Name -ErrorAction SilentlyContinue).$($protocolSetting.Name)
        $currentProtocolSettings += [PSCustomObject]@{ Path = $protocolSetting.Path; Name = $protocolSetting.Name; Value = $value }
    }
    Write-Verbose -Message "Schannel Protocol Settings: $($currentProtocolSettings | Format-Table -Autosize | Out-String)" -Verbose

    $observed = $currentProtocolSettings | ConvertTo-Json -Compress
    $expected = $protocolSettings | ConvertTo-Json -Compress

    # Is update needed?
    if ($observed -ne $expected)
    {
        # Create registry nodes.
        $protocolPaths = @(
            "$regPath\SSL 2.0"
            "$regPath\SSL 2.0\Client"
            "$regPath\SSL 2.0\Server"
            "$regPath\SSL 3.0"
            "$regPath\SSL 3.0\Client"
            "$regPath\SSL 3.0\Server"
            "$regPath\TLS 1.0"
            "$regPath\TLS 1.0\Client"
            "$regPath\TLS 1.0\Server"
            "$regPath\TLS 1.1"
            "$regPath\TLS 1.1\Client"
            "$regPath\TLS 1.1\Server"
            "$regPath\TLS 1.2"
            "$regPath\TLS 1.2\Client"
            "$regPath\TLS 1.2\Server"
        )
        foreach ($protocolPath in $protocolPaths)
        {
            if (-not (Get-Item -Path $protocolPath -ErrorAction SilentlyContinue))
            {
                New-Item -Path $protocolPath -ItemType Container -Force | Out-Null
            }
        }

        # Write updated values.
        foreach ($protocolSetting in $protocolSettings)
        {
            Set-ItemProperty -Path $protocolSetting.Path -Name $protocolSetting.Name -Value $protocolSetting.Value -Force
        }

        # Read updated values.
        $currentProtocolSettings = @()
        foreach ($protocolSetting in $protocolSettings)
        {
            $value = (Get-ItemProperty -Path $protocolSetting.Path -Name $protocolSetting.Name -ErrorAction SilentlyContinue).$($protocolSetting.Name)
            $currentProtocolSettings += [PSCustomObject]@{ Path = $protocolSetting.Path; Name = $protocolSetting.Name; Value = $value }
        }
        Write-Verbose -Message "Schannel Protocol Settings (updated): $($currentProtocolSettings | Format-Table -Autosize | Out-String)" -Verbose

        # It is necessary to restart the computer after modifying this setting for the changes to take effect.
        Write-Warning -Message "Schannel Protocols updated; it is necessary to restart the computer."
        $reboot = $true ### TODO: Restart-Computer -Force -Verbose
    }

    return $reboot
}

#-------------------------------------------------------------------------------
# Main

$reboot = $false
$reboot += Set-HttpSysSettings
$reboot += Set-SchannelCipherOrder
$reboot += Set-SchannelProtocols
if ($reboot)
{
    Write-Warning -Message "Restart the computer for settings to take effect."
    # TODO: Restart-Computer -Force -Verbose
}

You can also run SSL/TLS validation tools to identify other areas for improvement.

Back to top

Sign in to the management portal from multiple accounts

Pertains to: Windows Azure Pack for Windows Server Automation with Windows PowerShell

Issue

You need to be able to sign in to the management portal from multiple accounts.

Recommendation

Use the Add-MgmtSvcAdminUser Windows PowerShell cmdlet to add additional principals. These principals can be explicit users or security groups (if your tokens contain security group information). The following example adds a user. (It assumes that the password has been defined for the $pwd variable.)

Add-MgmtSvcAdminUser -Server 'mysqlserver' -UserName 'sa' -Password $pwd -Principal 'user7@contoso.com'

Back to top

See Also

Windows Azure Pack troubleshooting