Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Azure DevOps Powershell script Could not create SSL/TLS secure channel

Problem:
If I call command Get-AzureDeployment(also Get-AzureService) from 'Azure Powershell' task in DevOps Pipeline I am getting: 'The request was aborted: Could not create SSL/TLS secure channel.'

Introduction:

  • I use Azure DevOps to deploy Azure Cloud service (classic) into Azure
  • The 'Azure Powershell' task was working the whole time but then without changing anything it stopped working
  • I have also imported the certificate(used by DevOps) into my pc (by Import-AzurePublishSettingsFile) and tried to run the same powershell script and everytnig works fine so I expect problem in DevOps

DevOps connection:

  • I have created 'Service connection' in Azure DevOps to connect into Azure
  • The Service connection is type of 'Azure Classic' (because 'Azure Resource Manager' is not for 'Cloud service classic')
  • Autentication method of the 'Azure Classic service connection' is 'Certificate based'.
  • I used certificate generated by 'Publish Settings File' for my azure subscription. The certificate was placed by azure into My-subscription->Management certificates (expiration date is in mid 2021)
  • I use this service connection for deploying app (Cloud service classic) into Azure with no problem (by DevOps task 'Azure Cloud Service deployment') but just the 'Azure Powershell' task start failing.

This all was working for 3 months and then stopped working for any reason. The weird thing is that when I was playing with DevOps to find out what is wrong the task was once successfully run, but when I tried that again I got the error again.

I have both logs, from sucessful call and failing call. 2506 lines of logs are identical and the change is after this line.

I can send you both full logs but I don't want to place here so long logs.

Successful try:

VERBOSE: 8:31:40 AM - Begin Operation: Get-AzureDeployment
VERBOSE: 8:31:42 AM - Completed Operation: Get-AzureDeployment
... some other info about the deployment in slot

Log from failing call:

VERBOSE: 9:53:39 AM - Begin Operation: Get-AzureDeployment
##[debug]Caught exception from task script.
##[debug]Error record:
##[debug]Get-AzureDeployment : An error occurred while sending the request.
##[debug]At D:\a\r1\a\_Tools\Powershell\cloud-service_swap-slot.ps1:14 char:15
##[debug]+ ... eployment = Get-AzureDeployment -Slot "Staging" -ServiceName $CloudSe ...
##[debug]+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
##[debug]    + CategoryInfo          : CloseError: (:) [Get-AzureDeployment], HttpRequestException
##[debug]    + FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.ServiceManagement.HostedServices.GetAzureDeploymentComma    nd
##[debug] 
##[debug]Script stack trace:
##[debug]at <ScriptBlock>, D:\a\r1\a\_Tools\Powershell\cloud-service_swap-slot.ps1: line 14
##[debug]at <ScriptBlock>, <No file>: line 1
##[debug]at <ScriptBlock>, D:\a\_tasks\AzurePowerShell_72a1931b-effb-4d2e-8fd8-f8472a07cb62\3.171.2\AzurePowerShell.ps1: line 145
##[debug]at <ScriptBlock>, D:\a\_tasks\AzurePowerShell_72a1931b-effb-4d2e-8fd8-f8472a07cb62\3.171.2\AzurePowerShell.ps1: line 141
##[debug]at <ScriptBlock>, <No file>: line 1
##[debug]at <ScriptBlock>, <No file>: line 22
##[debug]at <ScriptBlock>, <No file>: line 18
##[debug]at <ScriptBlock>, <No file>: line 1
##[debug]Exception:
##[debug]System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
##[debug]   at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
##[debug]   at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
##[debug]   --- End of inner exception stack trace ---
##[debug]   at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
##[debug]   at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task)
##[debug]   at Microsoft.WindowsAzure.Management.Compute.DeploymentOperationsExtensions.GetBySlot(IDeploymentOperations operations, String serviceName, DeploymentSlot deploymentSlot)
##[debug]   at Microsoft.WindowsAzure.Commands.Utilities.Common.ServiceManagementBaseCmdlet.ExecuteClientActionNewSM[TResult](Object input, String operationDescription, Func`1 action, Func`3 contextFactory)
##[error]An error occurred while sending the request.
##[debug]Processed: ##vso[task.logissue type=error]An error occurred while sending the request.
##[debug]Processed: ##vso[task.complete result=Failed]

In both logs I can also find this for adding Azure account into Powershell:

##[debug]Added certificate to the certificate store.
##[command]Set-AzureSubscription -SubscriptionName PXX -SubscriptionId XXXXXX01-09f5-4703-bcc9-6ff914XXXXXX -Certificate ******** -Environment AzureCloud 
##[command]Select-AzureSubscription -SubscriptionId XXXXXX01-09f5-4703-bcc9-6ff914XXXXXX
##[debug]Leaving Initialize-Azure.
## Initializing Azure Complete 

(I have replaced some strings with X)

There is the Powershell task in YAML:

steps:
- task: AzurePowerShell@3
  displayName: 'Swap slots'
  inputs:
    azureConnectionType: ConnectedServiceName
    azureClassicSubscription: 'PXX subscription'
    ScriptPath: '$(System.DefaultWorkingDirectory)/_Tools/Powershell/cloud-service_swap-slot.ps1'
    ScriptArguments: '-CloudServiceName $(CloudServiceName)'
    FailOnStandardError: true
    azurePowerShellVersion: LatestVersion

And the Powershell script for swapping slots that works from local pc (with the same cert) but failing in DevOps:

[CmdletBinding(PositionalBinding=$True)]
Param(
    [Parameter(Mandatory = $true)]
    [String]$CloudServiceName              # required
)

# Check if Windows Azure Powershell is avaiable 
if ((Get-Module -ListAvailable Azure) -eq $null) 
{ 
    throw "Windows Azure Powershell not found! Please install from http://www.windowsazure.com/en-us/downloads/#cmd-line-tools" 
} 
 
# VIP Swap
$Deployment = Get-AzureDeployment -Slot "Staging" -ServiceName $CloudServiceName #It's failing here
if ($Deployment -ne $null -AND $Deployment.DeploymentId  -ne $null) 
{ 
     Write-Output ("Current Status of staging in {0}" -f $CloudServiceName); 
     Write-Host ($Deployment | Select-Object -Property * -ExcludeProperty Configuration,RolesConfiguration | Format-List | Out-String);

     $MoveStatus = Move-AzureDeployment -ServiceName $CloudServiceName 
     Write-Output ("Vip swap of {0} status: {1}" -f $CloudServiceName, $MoveStatus.OperationStatus)     
}else 
{ 
     Write-Output ("There is no deployment in staging slot of {0} to swap." -f $CloudServiceName) 
} 

Does anyone the same experience like me? Where could be the problem?

# Update

I have tried to add this security protocol setting at the begining of the script but with the same error.

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
like image 215
Petofi Avatar asked Sep 17 '20 14:09

Petofi


5 Answers

This appears to be an issue with the Microsoft build agents, but adding the following code to the beginning of each Azure Powershell task seems to have resolved this for us until they can figure that out.

$pcert = (Get-Variable Endpoint -ValueOnly).Auth.Parameters.certificate
$bytes = [convert]::FromBase64String($pcert) 
[IO.File]::WriteAllBytes("C:\cert.pfx",$bytes) 
$null = Import-PfxCertificate -FilePath C:\cert.pfx -CertStoreLocation cert:\CurrentUser\My
like image 102
keyset Avatar answered Oct 28 '22 22:10

keyset


There are few workarounds which are working.

  1. Workaround 1

    1. Use Azure Powershell Task Version 5
    2. Select "Azure Resource Manager Connection"
    3. Change ASM Module commands to Az commands
  2. Workaround 2

    1. Use Azure Powershell Task Version 3
    2. Classic Connection
    3. Downgrade Azure Powershell Version to 4.2.1
  3. Workaround 3 (for private agents)

    1. Create a self-signed cert in your CurrentUser\My store. you can find details on creating a self-signed cert here: https://learn.microsoft.com/en-us/azure/cloud-services/cloud-services-certs-create
    2. Export the public key for the cert as a DER-encoded CER file (you can use mmc or any other cert tool for this)
    3. Upload the .Cer file as a management certificate through the portal: https://learn.microsoft.com/en-us/previous-versions/azure/azure-api-management-certs
    4. Authenticate using Set-AzureSubscription:
     PS C:\> Clear-AzureProfile
     PS C:\> $cert = Get-Item Cert:\CurrentUser\My\
     PS C:\ > Set-AzureSubscription -SubscriptionName "" -SubscriptionId  -Certificate $cert
     PS C:\> Select-AzureSubscription -SubscriptionId 
     
  4. Workaround 4

    1. Add below script to each Azure Powershell task

        $p = (Get-Variable Endpoint -ValueOnly).Auth.Parameters.certificate
        $bytes = [convert]::FromBase64String($p)
        [IO.File]::WriteAllBytes("C:\cert.pfx",$bytes)
        Import-PfxCertificate -FilePath C:\cert.pfx -CertStoreLocation cert:\CurrentUser\My
        .
        .
        actual script
        .
        .
        #remove certificate from store
        $thumb = (Get-PfxData -FilePath "C:\cert.pfx").EndEntityCertificates.Thumbprint
        Remove-Item -Path cert:\CurrentUser\My\$thumb -recurse -Force
      
like image 36
Amruta Kawade Avatar answered Oct 28 '22 23:10

Amruta Kawade


We had the same issue. It only manifested on windows-2019 agents, not vs2017-win2016. So you could fix it by changing the agent type, but a better fix is to use a specific Powershell version of 5.1.1 instead of latest. It seems that latest recently increased to 5.3.0 which causes this error.

like image 1
Neil Avatar answered Oct 28 '22 23:10

Neil


I have the same issue and tried all these, for me it worked only if I added this after the Initialize-Azure part: "Set-AzureSubscription -SubscriptionId [my subscription id] -CurrentStorageAccountName [storage name]"

like image 1
Balla Győző Avatar answered Oct 29 '22 00:10

Balla Győző


This issue is caused by a change of behavior introduced with the .NET September update. The following code will restore implicit storage of keys (the previous .Net 4.x behavior) through an environment variable:

Set-Item env:\COMPLUS_CngImplicitPersistKeySet 1

NOTE: You will then need to create a new publishsettings file, as the old certificate and keys will not be overwritten by a subsequent import.

like image 1
Damien Caro Avatar answered Oct 28 '22 23:10

Damien Caro