0
votes

I have to restart cloud service instance on specified schedule through azure function. For this I am using Azure Resource Manager API. For that I am getting 403 error. 1.I have created APP registration in Azure AD. 2.Given contributor role to it. 3.Used application client id, client secret, tenant at required places. Below is the code:

private static async Task<string> GetAccessToken(string tenantName, string clientId, string clientSecret)
    {
        var authString = "https://login.microsoftonline.com/" + tenantName;
        var resourceUrl = "https://management.core.windows.net/";
        var authenticationContext = new AuthenticationContext(authString, false);
        var clientCred = new ClientCredential(clientId, clientSecret);
        var authenticationResult = await authenticationContext.AcquireTokenAsync(resourceUrl, clientCred);
        var token = authenticationResult.AccessToken;
        return token; 
    }

    [FunctionName("RestartWorkerJob")]
    public static void Run([TimerTrigger("0 */1 * * * *")]TimerInfo myTimer, TraceWriter log)
    {
        var tenantName = "";
        var clientId = "";
        var clientSecret = "";

        var token = GetAccessToken(tenantName, clientId, clientSecret).Result;

        string url = "https://management.core.windows.net/{subscription_id}/services/hostedservices/testworkerrole/deployments/{deployment_name}/roleinstances/WorkerRole1_IN_0";

        var client = new HttpClient();
        var request = new HttpRequestMessage()
        {
            RequestUri = new Uri(url),
            Method = HttpMethod.Post
        };

        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
        client.DefaultRequestHeaders.Add("x-ms-version", DateTime.UtcNow.ToShortDateString());
        client.DefaultRequestHeaders.Add(HttpRequestHeader.ContentLength.ToString(), "0");
        try
        {
            var task = client.SendAsync(request).ContinueWith((taskwithmsg) =>
            {
                var response = taskwithmsg.Result;

                var Text = response.Content.ReadAsStringAsync();

                if (response.IsSuccessStatusCode)
                {
                    log.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Info, "Restart was successful"));
                }
                else
                {
                    log.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Error, "Restart was unsuccessful"));
                }
            });
        }
        catch (Exception ex)
        {
            log.Trace(new TraceEvent(System.Diagnostics.TraceLevel.Error, ex.Message));
        }}

using this approach gives me error 403-forbidden. The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription.

I can't understand what's wrong here.

1
Does this code work locally? Can you confirm the token you are getting is valid, and maybe try using it yourself in a curl or Postman request to validate the token is valid?jeffhollan
Token seems to be valid as it gives me 403 forbidden, when token is invalid it give 401 unauthorized. that's I have checked.D. Jayesh

1 Answers

2
votes

The error 403 could be caused by permission issue or SPN expired.

When you register your web app with azure ad, for API permissions, select Azure Service Management. Select Delegated permissions and user_impersonation.

enter image description here

Refer to this article to use Resource Manager authentication API.