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

使用新版SDK在Azure App Service安装TLS证书遇404问题求助

(注:VB.NET或C#解答均可。)

使用新版Azure App Service SDK上传并安装第三方TLS证书遇到的问题

我在使用新版SDK安装已上传的证书时遇到问题,新版SDK未提供上传证书的方法,因此改用REST API完成上传操作。旧版SDK支持上传功能但已被弃用,技术迭代要求必须使用新版。

上传操作返回202状态码,看似成功,但Azure门户中并未显示该证书。推送站点数据更新时出现404错误:

状态:404(未找到)- 证书370A4097E85476AE65545702B410866882AD4541未找到。

该指纹与pfx证书的指纹完全匹配,确认这部分无问题。

上传代码

oApiCert = New Certificate With {.Location = oWebSiteData.Location.DisplayName}
oApiCert.Properties.CanonicalName = sCanonicalName
oApiCert.Properties.ServerFarmId = oWebSiteData.AppServicePlanId.ToString
oApiCert.Properties.Password = My.Resources.PfxPassword
oApiCert.Properties.PfxBlob = oX509Cert.Export(X509ContentType.Pfx, My.Resources.PfxPassword)
oApiCert.Properties.HostNames.AddRange(oX509Cert.SanHostNames)

sJsonContent = JsonConvert.SerializeObject(oApiCert, JsonHelper.DefaultSerializationSettings)
oContent = New StringContent(sJsonContent, Encoding.UTF8, "application/json")

oClient = New HttpClient
oClient.DefaultRequestHeaders.Add("Authorization", "Bearer " & oToken.Token)
oClient.BaseAddress = New Uri(My.Resources.ManagementEndpoint)

oResponse = Await oClient.PutAsync(sUrl, oContent)
oResponse.EnsureSuccessStatusCode()

更新代码

oSslStates = oWebSiteData.HostNameSslStates

oHostNames = oHostNames.Intersect(oWebSiteData.HostNames).ToList
oHostNames.ForEach(Sub(HostName)
                     oSslState = oSslStates.FirstOrDefault(Function(SslState) SslState.Name = HostName)

                     If oSslState Is Nothing Then
                       oSslState = New HostNameSslState With {.Name = HostName}
                       oSslStates.Add(oSslState)
                     End If

                     oSslState.Thumbprint = BinaryData.FromObjectAsJson(oX509Cert.Thumbprint)
                     oSslState.SslState = HostNameBindingSslState.SniEnabled
                     oSslState.ToUpdate = True
                   End Sub)

oSitePatch = New SitePatchInfo

For Each oState In oSslStates
  If oState.ToUpdate Then
    oSitePatch.HostNameSslStates.Add(oState)
  End If
Next

oWebSiteResource.Update(oSitePatch) ' <-- 404 here '

这段代码移植自LetsEncrypt-SiteExtension包,原库依赖旧版SDK。

新版SDK的文档和代码示例极为匮乏,我并非一定要按当前方式实现,只要方案可行即可。请问如何使用新版SDK在Azure App Service上上传并安装第三方TLS证书?有人成功实现过吗?

完整代码

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Net.Http
Imports System.Security.Cryptography.X509Certificates
Imports System.Text
Imports System.Threading.Tasks
Imports Azure
Imports Azure.Core
Imports Azure.Identity
Imports Azure.ResourceManager
Imports Azure.ResourceManager.AppService
Imports Azure.ResourceManager.AppService.Models
Imports Azure.ResourceManager.Resources
Imports Matrix.Common
Imports Newtonsoft.Json
Imports Nito.AsyncEx

Friend Module Program
  Friend Sub Main()
    AsyncContext.Run(Async Function()
                       Await UploadCert()
                     End Function)
  End Sub



  Private Async Function UploadCert() As Task
    Dim oWebSiteResponse As Response(Of WebSiteResource)
    Dim oWebSiteResource As WebSiteResource
    Dim oResourceGroup As ResourceGroupResource
    Dim sCanonicalName As String
    Dim oSubscription As SubscriptionResource
    Dim oWebSiteData As WebSiteData
    Dim sJsonContent As String
    Dim oCredential As ClientSecretCredential
    Dim oSslStates As IList(Of HostNameSslState)
    Dim oHostNames As List(Of String)
    Dim aHostNames As String()
    Dim oSitePatch As SitePatchInfo
    Dim oArmClient As ArmClient
    Dim oResponse As HttpResponseMessage
    Dim oX509Cert As X509Certificate2
    Dim oSslState As HostNameSslState
    Dim aScopeUrl As String()
    Dim sCertName As String
    Dim oContext As TokenRequestContext
    Dim oContent As StringContent
    Dim oApiCert As Certificate
    Dim oClient As HttpClient
    Dim oToken As AccessToken
    Dim oUrl As List(Of String)
    Dim sUrl As String

    oX509Cert = Utils.GetCertificate(My.Resources.CertFriendlyName)
    aHostNames = My.Resources.HostNames.Split(",", StringSplitOptions.RemoveEmptyEntries)
    oHostNames = New List(Of String)(aHostNames)
    sCanonicalName = oHostNames.First
    sCertName = $"{sCanonicalName}-{oX509Cert.Thumbprint}"

    oUrl = New List(Of String) From {
      "subscriptions",
      My.Resources.SubscriptionId,
      "resourceGroups",
      My.Resources.ResourceGroup,
      "providers",
      "Microsoft.Web",
      "certificates",
      sCertName
    }

    sUrl = String.Join("/", oUrl)
    sUrl = $"/{sUrl}?api-version=2022-03-01"

    oCredential = New ClientSecretCredential(My.Resources.TenantId, My.Resources.ClientId, My.Resources.ClientSecret)
    oArmClient = New ArmClient(oCredential)
    oSubscription = Await oArmClient.GetDefaultSubscriptionAsync
    oResourceGroup = Await oSubscription.GetResourceGroups.GetAsync(My.Resources.ResourceGroup)
    oWebSiteResponse = Await oResourceGroup.GetWebSiteAsync(My.Resources.AppServiceName)
    oWebSiteResource = oWebSiteResponse.Value
    oWebSiteData = oWebSiteResource.Data
    aScopeUrl = New String() {$"{My.Resources.ManagementEndpoint}.default"}
    oContext = New TokenRequestContext(aScopeUrl)
    oToken = Await oCredential.GetTokenAsync(oContext)

    oApiCert = New Certificate With {.Location = oWebSiteData.Location.DisplayName}
    oApiCert.Properties.CanonicalName = sCanonicalName
    oApiCert.Properties.ServerFarmId = oWebSiteData.AppServicePlanId.ToString
    oApiCert.Properties.Password = My.Resources.PfxPassword
    oApiCert.Properties.PfxBlob = oX509Cert.Export(X509ContentType.Pfx, My.Resources.PfxPassword)
    oApiCert.Properties.HostNames.AddRange(oX509Cert.SanHostNames)

    sJsonContent = JsonConvert.SerializeObject(oApiCert, JsonHelper.DefaultSerializationSettings)
    oContent = New StringContent(sJsonContent, Encoding.UTF8, "application/json")

    oClient = New HttpClient
    oClient.DefaultRequestHeaders.Add("Authorization", "Bearer " & oToken.Token)
    oClient.BaseAddress = New Uri(My.Resources.ManagementEndpoint)

    oResponse = Await oClient.PutAsync(sUrl, oContent)
    oResponse.EnsureSuccessStatusCode()

    oSslStates = oWebSiteData.HostNameSslStates

    oHostNames = oHostNames.Intersect(oWebSiteData.HostNames).ToList
    oHostNames.ForEach(Sub(HostName)
                         oSslState = oSslStates.FirstOrDefault(Function(SslState) SslState.Name = HostName)

                         If oSslState Is Nothing Then
                           oSslState = New HostNameSslState With {.Name = HostName}
                           oSslStates.Add(oSslState)
                         End If

                         oSslState.Thumbprint = BinaryData.FromObjectAsJson(oX509Cert.Thumbprint)
                         oSslState.SslState = HostNameBindingSslState.SniEnabled
                         oSslState.ToUpdate = True
                       End Sub)

    oSitePatch = New SitePatchInfo

    For Each oState In oSslStates
      If oState.ToUpdate Then
        oSitePatch.HostNameSslStates.Add(oState)
      End If
    Next

    oWebSiteResource.Update(oSitePatch) ' <-- 404 here '
  End Function
End Module

内容的提问来源于Stack Exchange,提问作者InteXX

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 20:47:01