Azure Service Management API - 403 forbidden error when trying to increase the number of instances of a service

Answered Azure Service Management API - 403 forbidden error when trying to increase the number of instances of a service

  • Monday, March 05, 2012 9:12 AM
     
     
     

    Hi there, i am trying to use the Azure Service Management API  to perform a configuration change for a hosted service. I believe I have followed the steps in doing this correctly but i keep on getting a 403 forbidden error when i try to get a response to my request to change the configuration. I think it is something got to do with the certificates. I can read off information about hosted services no problem. Only a change is causing a problem.

    I created a self signed cert and it is stored in the personal folder in the cert store. I then uploaded this cert as a management cert on Azure. I added
    this cert to the GET requests I make and it authenticates fine. If I use it with POST requests and i get a 403 forbidden error. I then created another self
    signed cert (also stored in the personal folder) and uploaded it as a serviceCert for the service i am trying to perform the POST request on. I add this cert to the  request as well as the the cert uploaded as a management cert. But i am still getting the 403 forbidden error.

    The code is below. Any advise?

    public void changeConfiguration(string serviceName,string deploymentSlot,string config, string deploymentName)

            {

                byte[] encodedConfigbyte = new byte[config.Length];

                encodedConfigbyte = System.Text.Encoding.UTF8.GetBytes(config);

                string encodedConfig = Convert.ToBase64String(encodedConfigbyte);

                Uri changeConfigRequestUri = new Uri("https://management.core.windows.net/" + subscriptionId + "/services/hostedservices/" + serviceName + "/deployments/" + deploymentName + "/?comp=config)");

                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(changeConfigRequestUri);

                request.Headers.Add("x-ms-version", "2010-10-28");

                request.Method = "POST";

                string bodyText = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +

                                  "<ChangeConfiguration xmlns=\"http://schemas.microsoft.com/windowsazure" + ">" +

                                  "<Configuration>" + encodedConfig + "</Configuration>" + "<TreatWarningsAsError>false</TreatWarningsAsError>" +

                                  "<Mode>Auto</Mode>" +"</ChangeConfiguration>";

                byte[] buf = Encoding.UTF8.GetBytes(bodyText);

                request.ContentType = "text/xml";

                request.ContentLength = buf.Length;

                StreamWriter writer = new StreamWriter(request.GetRequestStream());

                var data = Encoding.ASCII.GetBytes(buf.ToString());

                writer.Write(data);

                writer.Flush();

                writer.Close();

                X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);

                try

                {

                    certStore.Open(OpenFlags.ReadOnly);

                }

                catch (Exception e)

                {

                    if (e is CryptographicException)

                    {

                        Console.WriteLine("Error: The store is unreadable.");

                    }

                    else if (e is SecurityException)

                    {

                        Console.WriteLine("Error: You don't have the required permission.");

                    }

                    else if (e is ArgumentException)

                    {

                        Console.WriteLine("Error: Invalid values in the store.");

                    }

                    else

                    {

                        throw;

                    }

                }

                X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);

                //Hardcoded Thumbprint below is for the service certificate

                X509Certificate2Collection certCollection1 = certStore.Certificates.Find(X509FindType.FindByThumbprint, "‎2d22d789d56f68ce6469d7c70b6e334b16c98f8e", false);

                certStore.Close();

                if (certCollection.Count == 0)

                {

                    throw new Exception("Error: No certificate found containing thumbprint " + thumbprint);

                }

                X509Certificate2 certificate = certCollection[0];

                X509Certificate2 certificate1 = certCollection[0];

                request.ClientCertificates.Add(certificate);

                request.ClientCertificates.Add(certificate1);

               

                //error occurs below

                WebResponse response = (HttpWebResponse)request.GetResponse();

                try

                {

                    response = request.GetResponse();

                }

               catch (WebException e)

                {

                    string test = e.Message;

                }

            }


    • Edited by G Clynch Tuesday, March 06, 2012 2:55 PM
    •  

All Replies

  • Monday, March 05, 2012 2:14 PM
     
     

    Hi,

    If you try and read the response stream from your WebException, you will be able to get more details about this 403 errors. Please do the following in your WebException catch block:

    catch (WebException e)

                {

                    var resp = e.Response;
      if (resp != null)
      {
       using (StreamReader streamReader = new StreamReader(resp.GetResponseStream(), true))
                     {
                         string detailedErrorMessage = streamReader.ReadToEnd();
                     }   
      }

                }

    This should give you some more detailed information in "detailedErrorMessage" string in XML format.

    Hope this helps.

    Thanks

    Gaurav Mantri

    Cerebrata Software

    http://www.cerebrata.com

     

  • Monday, March 05, 2012 2:14 PM
     
     

    Hi G Clynch,

    Could you try using the URL with the deploymentslot instead of the one with the deployment name (http://msdn.microsoft.com/en-us/library/windowsazure/ee460809.aspx)?

    https://management.core.windows.net/<subscription-id>/services/hostedservices/<service-name>/deploymentslots/<deployment-slot>/?comp=config

    What values are you using for deploymentslot / deploymentname?

    Sandrino

  • Tuesday, March 06, 2012 2:57 PM
     
     

    Hi Gaurav,

    I did as you suggested and caught the web exception, but there is no detail  available on the error message, the description is empty.

    Thanks,

  • Tuesday, March 06, 2012 2:58 PM
     
     

    Hi Sandrino,

    I tried using the URL with the deployment slot as you suggested but I am still getting the 403 fobidden error.

    Thanks

  • Thursday, March 08, 2012 7:45 AM
    Moderator
     
     

    Hi,

    At the first glance the content type HTTP header seems wrong. According to:

    http://msdn.microsoft.com/en-us/library/windowsazure/ee460809.aspx

    It should be application/xml instead of text/xml. Could you change it to see whether it works?


    Allen Chen [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

  • Thursday, March 08, 2012 5:53 PM
     
     

    Hi Allen,

    I tried that but it is still not working. I am able to use the service management API to get information about hosted services etc. This has never been a problem. But once I try to change something e.g. no. of instances I get the 403 forbidden error. I have a management certificate installed in the subscription and am attaching the certificate to requests.

  • Thursday, March 08, 2012 6:13 PM
     
     

    Hi,

    Normally you get 403 error when there is an issue with the certificates. Since you mentioned that you're able to get information about hosted services, it looks like there might be an issue with the code above. Will it be possible for you to share the code that you're using to get information about hosted services. We can then compare them and see if there is anything different about your code above.

    I also noticed that you're adding two certificates to the request object in your code above:

     X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);

                //Hardcoded Thumbprint below is for the service certificate

                X509Certificate2Collection certCollection1 = certStore.Certificates.Find(X509FindType.FindByThumbprint, "‎2d22d789d56f68ce6469d7c70b6e334b16c98f8e", false);

                certStore.Close();

                if (certCollection.Count == 0)

                {

                    throw new Exception("Error: No certificate found containing thumbprint " + thumbprint);

                }

                X509Certificate2 certificate = certCollection[0];

                X509Certificate2 certificate1 = certCollection[0];

                request.ClientCertificates.Add(certificate);

                request.ClientCertificates.Add(certificate1);

    May I ask why? Could this be the reason?

    Hope this helps.

    Thanks

    Gaurav

  • Friday, March 09, 2012 2:18 AM
    Moderator
     
     Answered

    Hi,

    I think I found what the problem is... You're attaching your certificate to the request after you send the HTTP request... Please move this call:

    request.GetRequestStream()

    after where you call:

    request.ClientCertificates.Add(certificate);

    Other problems in your code:

    1. bodyText is invalid, missing bold part:

    "<ChangeConfiguration xmlns=\"http://schemas.microsoft.com/windowsazure\""

    2. Attached certificate twice.

    3. The code to post should be:

     Stream dataStream = request.GetRequestStream();

     dataStream.Write(buf, 0, buf.Length);

     dataStream.Close();

    The modified version based on your code:

     class Program
        {
            static void Main(string[] args)
            {
                Program p = new Program();
                p.Run();
            }
            string thumbprint = "[thumbprint]";
            void Run()
            {
                var subID="[subscription id]";
                var sname = "[service name]";
                var sdname = "[Production or Staging]";
                var config = File.ReadAllText("myconfig file path");
                changeConfiguration(subID, sname, config, sdname);
            }
            public void changeConfiguration(string subscriptionId,string serviceName,  string config, string deploymentName)
            {

                byte[] encodedConfigbyte = new byte[config.Length];

                encodedConfigbyte = System.Text.Encoding.UTF8.GetBytes(config);

                string encodedConfig = Convert.ToBase64String(encodedConfigbyte);

                Uri changeConfigRequestUri = new Uri("https://management.core.windows.net/" + subscriptionId + "/services/hostedservices/" + serviceName + "/deploymentslots/" + deploymentName + "/?comp=config");

                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(changeConfigRequestUri);

                request.Headers.Add("x-ms-version", "2010-10-28");

                request.Method = "POST";

                string bodyText = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +

                                  "<ChangeConfiguration xmlns=\"http://schemas.microsoft.com/windowsazure\"" + ">"

                                  + "</ChangeConfiguration>";

                byte[] buf = Encoding.UTF8.GetBytes(bodyText);

                request.ContentType = "application/xml";

                request.ContentLength = buf.Length;

            

                X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);

                try
                {

                    certStore.Open(OpenFlags.ReadOnly);

                }

                catch (Exception e)
                {

                    if (e is CryptographicException)
                    {

                        Console.WriteLine("Error: The store is unreadable.");

                    }

                    else if (e is SecurityException)
                    {

                        Console.WriteLine("Error: You don't have the required permission.");

                    }

                    else if (e is ArgumentException)
                    {

                        Console.WriteLine("Error: Invalid values in the store.");

                    }

                    else
                    {

                        throw;

                    }

                }

                X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);

                certStore.Close();

                if (certCollection.Count == 0)
                {

                    throw new Exception("Error: No certificate found containing thumbprint ");

                }

                X509Certificate2 certificate = certCollection[0];

                    request.ClientCertificates.Add(certificate);

                     Stream dataStream = request.GetRequestStream();


                dataStream.Write(buf, 0, buf.Length);


                dataStream.Close();

                try
                {
                WebResponse response = (HttpWebResponse)request.GetResponse();
                 }

                catch (WebException e)
                {

                  // code here
                }

            }


        }


    Allen Chen [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Allen Chen [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.