Blog de Florent Appointaire

Blog sur les technologies Microsoft (Windows Server, System Center, Azure, Windows Azure Pack/Azure Stack, etc;)

[WAP] Erreur lors de l’exécution de la commande Get-MgmtSvcResourceProvider avec ADFS

system_center_2012_logo

Après avoir modifié l’authentification de WAP vers ADFS, j’ai voulu reconfiguré les différents resources providers pour les faire pointer vers un F5 (Load Balancer). J’ai utilisé la commande de base pour récupéré mon jeton (Get-MgmtSvcToken) mais j’ai reçu l’erreur suivante:

Get-MgmtSvcResourceProvider : The security token cannot be verified.
At line:29 char:7
+ $rp = Get-MgmtSvcResourceProvider -Name $resourceProviderName -IncludeSystemReso ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-MgmtSvcResourceProvider], ManagementClientException
    + FullyQualifiedErrorId : Microsoft.WindowsAzure.Server.Management.ManagementClientException,Microsoft.WindowsAzure.Admin.PowerShell.GetResourceProvider

Après quelques recherches, je suis tombé sur cet article Microsoft: https://technet.microsoft.com/en-us/library/bab7a8c3-b71b-4e87-ad0f-db1f3acf0b1d#C_GetMgmtSvcToken

Dans la partie Issue, il est bien précisé l’erreur que j’ai.
Dans la partie Recommendation, il est précisé que il peut y avoir des problème avec la commande Get-MgmtSvcToken si on utilize un ADFS. Microsoft fournit alors un script PowerShell qui remplace la commande Get-MgmtSvcToken:

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

Il vous faudra remplacé les variables $adfsAddress par l’adresse de votre serveur ADFS et $username & $password par les credentials qui ont les droits de changer ce resources providers.

Facebook Like
Anonymous