Сбой сборки конвейера Azure DevOps Server при использовании самозаверяющего SSL-сертификата и невозможности получить сертификат локального эмитента во время восстановления NuGet

После обновления до Azure DevOps Server 2019 автоматические сборки конвейера не работают на этапе восстановления NuGet, показывая:

Ошибка: ошибка: невозможно получить сертификат местного эмитента

Пакеты не удалось восстановить

В документации Microsoft говорится что агент сборки, работающий в Windows, использует хранилище сертификатов Windows, поэтому я проверил, что требуемые сертификаты правильно установлены на сервере сборки, однако он по-прежнему не работает.

Есть много вопросов с похожими симптомами, но разными причинами. После расследования я нашел решение этой проблемы, но я ничего не заметил по этой конкретной проблеме, поэтому я опубликую ответ, который, надеюсь, сэкономит время кому-то еще!


person Andy Hames    schedule 02.07.2019    source источник


Ответы (3)


Оказывается, агент сборки Azure DevOps использует версию Node.js, которая не использует хранилище сертификатов Windows.

Требуемое решение состоит в том, чтобы указать Node.js на экспортированную копию (файл * .cer) корневого сертификата CA вашего самоподписанного SSL-сертификата, используя либо системную переменную среды с именем NODE_EXTRA_CA_CERTS, либо с помощью переменной задачи с именем NODE.EXTRA.CA.CERTS со значением указывая на сертификат.

Ссылка на проблему сообщества разработчиков < / а>

person Andy Hames    schedule 02.07.2019
comment
Я использовал команду powershell: [Environment]::SetEnvironmentVariable("NODE_EXTRA_CA_CERTS", "C:\Path\To\Certificates\our_certificate.cer", "Machine"), затем Get-service vstsagent* | stop-service -force и, наконец, Get-service vstsagent* | stop-service - person reckface; 27.11.2019
comment
Не знаю почему, но мне нужен был файл .pem. - person Robert Muehsig; 20.05.2020

Я использую задание агента PowerShell со следующим сценарием. Это эффективно дает возможность Node.JS «Использовать хранилище сертификатов компьютера Windows» для конвейера.

Некоторые примечания:

  • Мониторинг node.exe с помощью ProcMon предполагает, что файл, указанный в NODE_EXTRA_CA_CERTS, читается каждый раз при запуске конвейера. Однако другие предлагали запустить Restart-Service vstsagent* -Force, чтобы изменения были приняты. Это не мой опыт, но, возможно, что-то другое в разных средах вызывает такое поведение.

  • Это добавляет дополнительное время выполнения конвейера ~ 1 с. Вероятно, приемлемая цена за «установил и забыл управление сертификатами для Node in Pipelines в Windows», но, тем не менее, стоит отметить.

# If running in a pipeline then use the Agent Home directory,
# otherwise use the machine temp folder which is useful for testing
if ($env:AGENT_HOMEDIRECTORY -ne $null) { $TargetFolder = $env:AGENT_HOMEDIRECTORY }
else { $TargetFolder = [System.Environment]::GetEnvironmentVariable('TEMP','Machine') }

# Loop through each CA in the machine store
Get-ChildItem -Path Cert:\LocalMachine\CA | ForEach-Object {

    # Convert cert's bytes to Base64-encoded text and add begin/end markers
    $Cert = "-----BEGIN CERTIFICATE-----`n"
    $Cert+= $([System.Convert]::ToBase64String($_.export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert),'InsertLineBreaks'))
    $Cert+= "`n-----END CERTIFICATE-----`n"

    # Append cert to chain
    $Chain+= $Cert
}

# Build target path
$CertFile = "$TargetFolder\TrustedRootCAs.pem"

# Write to file system
$Chain | Out-File $CertFile -Force -Encoding ASCII

# Clean-up
$Chain = $null

# Let Node (running later in the pipeline) know from where to read certs
Write-Host "##vso[task.setvariable variable=NODE.EXTRA.CA.CERTS]$CertFile"
person alifen    schedule 08.01.2020

Я отформатировал сценарий PowerShell из @alifen. Приведенный ниже сценарий может быть выполнен в самом агенте сборки. Он принимает параметр для целевого пути и устанавливает переменную среды на сервере.

Кредит для @alifen


[CmdletBinding()]
param (
    [Parameter()]
    [string]
    $TargetFolder = "$env:SystemDrive\Certs"
)
If (-not(Test-Path $TargetFolder))
{
    $null = New-Item -ItemType Directory -Path $TargetFolder -Force
}
# Loop through each CA in the machine store
Get-ChildItem -Path Cert:\LocalMachine\CA | ForEach-Object {

    # Convert cert's bytes to Base64-encoded text and add begin/end markers
    $Cert = "-----BEGIN CERTIFICATE-----`n"
    $Cert += $([System.Convert]::ToBase64String($_.export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert), 'InsertLineBreaks'))
    $Cert += "`n-----END CERTIFICATE-----`n"

    # Append cert to chain
    $Chain += $Cert
}

# Build target path
$CertFile = "$TargetFolder\TrustedRootCAs.pem"

# Write to file system
Write-Host "[$($MyInvocation.MyCommand.Name)]: Exporting certs to: [$CertFile]"
$Chain | Out-File $CertFile -Force -Encoding ASCII

# Set Environment variable
Write-Host "[$($MyInvocation.MyCommand.Name)]: Setting environment variable [NODE_EXTRA_CA_CERTS] to [$CertFile]"
[Environment]::SetEnvironmentVariable("NODE_EXTRA_CA_CERTS", "$CertFile", "Machine")

person Dejulia489    schedule 23.12.2020