简体   繁体   中英

C# .Net Azure Management REST API - Add App Service Managed Certificate - Response = Not Found

I can use the Azure Management REST API to add a custom domain to my Azure App Service. I also need to secure that custom domain by adding a App Managed Certificate to my app service.

static string _ClientId = Startup.StaticConfig.GetValue<string>("Azure:ClientId");
static string _ClientKey = Startup.StaticConfig.GetValue<string>("Azure:ClientSecret");
static string _TenantId = Startup.StaticConfig.GetValue<string>("Azure:TenantId");
static string _SubscriptionId = Startup.StaticConfig.GetValue<string>("Azure:SubscriptionId");
static string _ResourceGroupName = Startup.StaticConfig.GetValue<string>("Azure:ResourceGroupName");
static string _AppName = Startup.StaticConfig.GetValue<string>("Azure:AppName");
static string _AppServicePlanName = Startup.StaticConfig.GetValue<string>("Azure:AppServicePlanName");

public static string ResourceGroupName { get => _ResourceGroupName; set => _ResourceGroupName = value; }

public static async Task<HttpStatusCode> AddHostNameFromForumResponse(string sHostName)
{
    HttpResponseMessage responseMessage;
    var appId = _ClientId;
    var secretKey = _ClientKey;
    var tenantId = _TenantId;
    var context = new AuthenticationContext("https://login.windows.net/" + tenantId);
    ClientCredential clientCredential = new ClientCredential(appId, secretKey);
    var tokenResponse = context.AcquireTokenAsync("https://management.azure.com/", clientCredential).Result;
    var accessToken = tokenResponse.AccessToken;
    
    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
        var baseUrl = new Uri($"https://management.azure.com/");
        var requestURl = baseUrl + $"subscriptions/{_SubscriptionId}/resourceGroups/{_ResourceGroupName}/providers/Microsoft.Web/sites/{_AppName}/hostNameBindings/{sHostName}?api-version=2016-08-01";
        string body = $"{{\"properties\": {{\"azureResourceName\": \"{_AppName}\"}}}}";
        var stringContent = new StringContent(body, Encoding.UTF8, "application/json");
        responseMessage = await client.PutAsync(requestURl, stringContent);


        if (((long)responseMessage.StatusCode == 200)) // Trying to create the app managed certificate here
        {
            //requestURl = baseUrl + $"subscriptions/{_SubscriptionId}/resourceGroups/{_ResourceGroupName}/providers/Microsoft.Web/certificates/{sHostName}?api-version=2019-08-01";
            requestURl = baseUrl + $"subscriptions/{_SubscriptionId}/resourceGroups/{_ResourceGroupName}/providers/Microsoft.Web/certificates/{sHostName}?api-version=2021-02-01";
            var serverFarm = $"/subscriptions/{_SubscriptionId}/resourceGroups/{_ResourceGroupName}/providers/Microsoft.Web/serverfarms/{_AppServicePlanName}";
            body = $"{{\"location\": \"West US\", \"properties\": {{\"canonicalName\": \"{sHostName}\", \"hostNames\": [\"{sHostName}\"], \"serverFarmId\": \"{serverFarm}\"}}}}";
            stringContent = new StringContent(body, Encoding.UTF8, "application/json");
            responseMessage = await client.PutAsync(requestURl, stringContent);
        }
    }

    return responseMessage.StatusCode;

I can add the domain, but when I try to PUT the app managed certificate, I get response message 404 - Not Found .

I was originally following https://docs.microsoft.com/en-us/answers/questions/491924/creating-app-service-managed-certificates-via-api.html which has an api version of 2019-08-01, but then I found https://docs.microsoft.com/en-us/rest/api/appservice/certificates/create-or-update which has an api version of 2021-02-01.

I am confused by the serverFarm AppServicePlanName .

应用服务计划

Notice the (B1: 1) . Not sure if that is part of the app service name or not. I've tried it with and without. It didn't seem to make a difference.

Here are the relevant values:

requestUrl = https://management.azure.com/subscriptions/xxx-xx-4c7e01d9a379/resourceGroups/MyResourceGroup/providers/Microsoft.Web/certificates/contoso.com?api-version=2021-02-01

serverFarm = /subscriptions/xxx-xx-4c7e01d9a379/resourceGroups/MyResourceGroup/providers/Microsoft.Web/serverfarms/ResourceGroup-80c2

{"location": "East US", "properties": {"canonicalName": "contoso.com", "hostNames": ["contoso.com"], "serverFarmId": "/subscriptions/9497817f-xxxx-479a-bb9f-4c7e01d9a379/resourceGroups/MyShoppingCartResourceGroup/providers/Microsoft.Web/serverfarms/ASP-ResourceGroup-80c2"}}

请求正文

Why would I be getting a 404 Not Found? Anyone have any ideas?

EDIT: Sharing the Answer

I figured out the problem. Apparently there are 2 different versions of the App Service Plan name. I assume this is just to over-complicate things. This wasn't an issue when I was creating the domain. It was only an issue when creating the certificate for the domain. And you have to use both versions of the App Service Plan name in the serverFarm when creating the certificate. See the screen shot from my App Service Plan:

在此处输入图像描述

Here is the correct version of the serverFarm Id:

/subscriptions/xxx-xx-xxxx-xx-xxx-4c7e01d9a379/resourceGroups/X-XXX-Resource-Group/providers/Microsoft.Web/serverfarms/XXX-XXXResourceGroup-80c2

After /resourceGroups put the one that I highlighted in Yellow. After serverfarms put the other one, without the (B1: 1).

Here is the full code I used to create the custom domain, and to create the certificate.

using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace MyShoppingCart.Helpers.ManagementLibrarySample
{
    public class ManagementLibrarySample
    {

        static string _ClientId = Startup.StaticConfig.GetValue<string>("Azure:ClientId");
        static string _ClientKey = Startup.StaticConfig.GetValue<string>("Azure:ClientSecret");
        static string _TenantId = Startup.StaticConfig.GetValue<string>("Azure:TenantId");
        static string _SubscriptionId = Startup.StaticConfig.GetValue<string>("Azure:SubscriptionId");
        static string _ResourceGroupName = Startup.StaticConfig.GetValue<string>("Azure:ResourceGroupName");
        static string _AlternateResourceGroupName = Startup.StaticConfig.GetValue<string>("Azure:AlternateResourceGroupName");
        static string _AppName = Startup.StaticConfig.GetValue<string>("Azure:AppName");
        static string _AppServicePlanName = Startup.StaticConfig.GetValue<string>("Azure:AppServicePlanName");

        public static async Task<HttpStatusCode> AddHostNameFromForumResponse(string sHostName)
        {
            HttpResponseMessage responseMessage;
            var appId = _ClientId;
            var secretKey = _ClientKey;
            var tenantId = _TenantId;
            var context = new AuthenticationContext("https://login.windows.net/" + tenantId);
            ClientCredential clientCredential = new ClientCredential(appId, secretKey);
            var tokenResponse = context.AcquireTokenAsync("https://management.azure.com/", clientCredential).Result;
            var accessToken = tokenResponse.AccessToken;

            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
                var baseUrl = new Uri($"https://management.azure.com/");
                var requestURl = baseUrl + $"subscriptions/{_SubscriptionId}/resourceGroups/{_ResourceGroupName}/providers/Microsoft.Web/sites/{_AppName}/hostNameBindings/{sHostName}?api-version=2016-08-01";
                string body = $"{{\"properties\": {{\"azureResourceName\": \"{_AppName}\"}}}}";
                var stringContent = new StringContent(body, Encoding.UTF8, "application/json");
                responseMessage = await client.PutAsync(requestURl, stringContent);


                if (((long)responseMessage.StatusCode == 200)) // Trying to create the app managed certificate here
                {
                    requestURl = baseUrl + $"subscriptions/{_SubscriptionId}/resourceGroups/{_ResourceGroupName}/providers/Microsoft.Web/certificates/{sHostName}?api-version=2021-02-01";

                    var serverFarm = $"/subscriptions/{_SubscriptionId}/resourceGroups/{_AlternateResourceGroupName}/providers/Microsoft.Web/serverfarms/{_AppServicePlanName}";

                    body = $"{{\"location\": \"West US\", \"properties\": {{\"canonicalName\": \"{sHostName}\", \"hostNames\": [\"{sHostName}\"], \"serverFarmId\": \"{serverFarm}\"}}}}";

                    stringContent = new StringContent(body, Encoding.UTF8, "application/json");
                    responseMessage = await client.PutAsync(requestURl, stringContent);
                }
            }

            return responseMessage.StatusCode;
        }
    }
}

This new variable named _AlternateResourceGroupName is the one highlighted in yellow from my original post.

What I still need to figure out is how to associate and bind the certificate to the custom domain name. If anyone has any idea, please let me know.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM