You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Pipelines重复部署.NET Web应用遇SSL错误183,求更优方案

解决IISWebAppManagementOnMachineGroup@0后续部署SSL证书183错误问题

问题场景

使用Azure Pipelines的IISWebAppManagementOnMachineGroup@0任务将.NET Web应用部署到Windows Server 2022时,首次部署完全正常,但后续部署会抛出以下错误:

SSL Certificate add failed, Error: 183
Cannot create a file when that file already exists.

当前临时解决方案是在部署前通过PowerShell任务删除对应主机名和端口的SSL绑定,但需要无需每次删除证书的更优方案。

优化解决方案

方案1:拆分部署逻辑,避免重复添加绑定

首次部署时使用CreateOrUpdateWebsite操作创建网站并添加SSL绑定,后续部署仅更新网站核心属性(如物理路径、应用池配置),不再重复处理绑定:

  • 首次部署任务保持原配置不变;
  • 后续部署任务修改ActionIISWebsite为UpdateWebsite,同时移除AddBinding: true和Bindings相关配置:
- task: IISWebAppManagementOnMachineGroup@0
  inputs:
    IISDeploymentType: 'IISWebsite'
    ActionIISWebsite: 'UpdateWebsite'
    WebsiteName: '${{ parameters.websiteName }}'
    WebsitePhysicalPath: '${{ parameters.physicalPath }}'
    WebsitePhysicalPathAuth: 'WebsiteUserPassThrough'
    CreateOrUpdateAppPoolForWebsite: true
    AppPoolNameForWebsite: '${{ parameters.websitePoolName }}'
    DotNetVersionForWebsite: 'No Managed Code'
    PipeLineModeForWebsite: 'Integrated'
    AppPoolIdentityForWebsite: 'ApplicationPoolIdentity'
    ConfigureAuthenticationForWebsite : true
    AnonymousAuthenticationForWebsite: false
    WindowsAuthenticationForWebsite: true

方案2:添加条件判断,仅当绑定不存在时执行添加操作

在IIS管理任务前添加PowerShell任务,检查目标hostname:443的SSL绑定是否已存在,通过变量控制是否执行添加绑定逻辑:

- task: PowerShell@2
  displayName: Check existing SSL binding
  name: CheckSSLBindings
  inputs:
    targetType: 'inline'
    script: |
      $bindingExists = netsh http show sslcert hostnameport=${{ parameters.hostname }}:443 | Select-String "${{ parameters.hostname }}:443"
      Write-Host "##vso[task.setvariable variable=NeedAddBinding]$(-not $bindingExists)"

- task: IISWebAppManagementOnMachineGroup@0
  inputs:
    IISDeploymentType: 'IISWebsite'
    ActionIISWebsite: 'CreateOrUpdateWebsite'
    WebsiteName: '${{ parameters.websiteName }}'
    WebsitePhysicalPath: '${{ parameters.physicalPath }}'
    WebsitePhysicalPathAuth: 'WebsiteUserPassThrough'
    CreateOrUpdateAppPoolForWebsite: true
    AppPoolNameForWebsite: '${{ parameters.websitePoolName }}'
    DotNetVersionForWebsite: 'No Managed Code'
    PipeLineModeForWebsite: 'Integrated'
    AppPoolIdentityForWebsite: 'ApplicationPoolIdentity'
    AddBinding: $(NeedAddBinding)
    Bindings: |
        {
            bindings:[
                {
                    "protocol":"https",
                    "ipAddress":"All Unassigned",
                    "hostname":"${{ parameters.hostname }}",
                    "port":"443",
                    "sslThumbprint":"${{ parameters.sslThumbprint }}",
                    "sniFlag":true
                }
            ]
        }
    ServerNameIndication: true
    ConfigureAuthenticationForWebsite : true
    AnonymousAuthenticationForWebsite: false
    WindowsAuthenticationForWebsite: true

方案3:预检查并更新绑定(替代删除操作)

通过PowerShell先检查绑定是否存在,若存在则验证证书指纹是否匹配,不匹配则更新;不存在则添加,避免删除绑定的操作:

- task: PowerShell@2
  displayName: Ensure SSL binding is configured correctly
  inputs:
    targetType: 'inline'
    script: |
      $targetHostPort = "${{ parameters.hostname }}:443"
      $certThumbprint = "${{ parameters.sslThumbprint }}".Replace(" ", "") # 去除指纹中的空格
      $appId = "{12345678-1234-1234-1234-1234567890AB}" # 使用固定GUID或从应用池获取

      # 检查绑定是否存在
      $existingBinding = netsh http show sslcert hostnameport=$targetHostPort 2>&1 | Select-String "Certificate Hash"
      
      if ($existingBinding) {
          $existingThumbprint = ($existingBinding -split ": ")[-1].Trim()
          if ($existingThumbprint -eq $certThumbprint) {
              Write-Host "SSL binding for $targetHostPort already uses the correct certificate."
          } else {
              Write-Host "Updating SSL binding to use the latest certificate..."
              netsh http update sslcert hostnameport=$targetHostPort certhash=$certThumbprint appid=$appId
          }
      } else {
          Write-Host "Adding new SSL binding for $targetHostPort..."
          netsh http add sslcert hostnameport=$targetHostPort certhash=$certThumbprint appid=$appId sslctlstorename=MY
      }

内容的提问来源于stack exchange,提问作者aro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 03:14:54