导出 (0) 打印
全部展开

删除服务证书

更新时间: 2014年9月

Delete Service Certificate异步操作从云服务的证书存储中删除服务证书。

可以按以下方式指定 Delete Service Certificate 请求。将 <subscription-id> 替换为订阅 ID,将 <service-name> 替换为云服务的 DNS 前缀名称,将 <thumbprint-algorithm> 替换为指纹的算法,并将 <thumbprint> 替换为指纹。

 

方法 请求 URI

DELETE

https://management.core.windows.net/<subscription-id>/services/hostedservices/<service-name>/certificates/<thumbprint-algorithm>-<thumbprint>

你必须确保向管理服务发出的请求是安全的。有关其他详细信息,请参见对服务管理请求进行身份验证

无。

下表介绍请求标头。

 

请求标头 说明

x-ms-version

必需。指定用于此请求的操作的版本。应将此标头设置为 2009-10-1 或更高版本。有关版本控制标头的更多信息,请参阅服务管理版本控制

无。

响应包括 HTTP 状态代码和一组响应标头。

此操作成功后返回状态代码 200(正常)。有关状态代码的信息,请参阅服务管理状态和错误代码

此操作的响应包括以下标头。该响应还可能包括其他标准 HTTP 标头。所有标准标头均符合 HTTP/1.1 协议规范

 

响应标头 说明

x-ms-request-id

一个值,它唯一地标识对管理服务做出的请求。对于异步操作,可使用此标头的值调用获取操作状态以确定操作是已完成、已失败还是仍在进行中。

无。

以下示例是一个控制台程序,它向指定的云服务添加 pfx 证书,然后从该云服务中删除此证书。若要运行该示例,请创建一个服务证书,然后将其与其私钥作为一个 pfx 文件保存在你的“文档”文件夹中。创建 pfx 文件形式的服务证书时,请向其提供一个密码,以后将该证书添加到你的云服务时将输入此密码。修改代码,用要在 x-ms-version 标头中使用的值更新 Version 字符。将 ManagementThumbprint 值设置为你的管理证书的指纹。将 SubscriptionId 值设置为订阅标识符,并将 ServiceName 设置为你的托管服务的 DNS 前缀名称。将 PfxFile 值设置为服务证书 pfx 文件的名称,并将 CertificateThumbprint 值设置为证书的指纹。运行该程序时,它请求服务证书 pfx 文件的密码。然后,它使用添加服务证书操作将该证书添加到云服务,并使用获取操作状态操作轮询异步结果。得到结果后,该程序使用列出服务证书操作显示云服务中的证书。然后,它使用Delete Service Certificate操作从云服务中删除该证书,并使用获取操作状态操作轮询异步结果。最后,它使用 列出服务证书 操作显示已删除的证书。有关如何创建证书、将其导出为 .pfx 文件和获取其指纹的详细信息,请参阅为 Azure 创建服务证书

namespace Microsoft.WindowsAzure.ServiceManagementRESTAPI.Samples
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    using System.Threading;
    using System.Xml;
    using System.Xml.Linq;
 
    public class Program
    {
        // Set these constants with your values to run the sample.
        private const string XMsVersion = "2011-10-01";
        private const string ManagementThumbprint = "management-certificate-thumbprint";
        private const string SubscriptionId = "subscription-identifier";
        private const string ServiceName = "service-dns-prefix-name";
        private const string PfxFile = "service-certificate-pfx-file";
        private const string CertificateThumbprint = "service-certificate-thumbprint";
 
        // This is the common namespace for all Service Management REST API XML data.
        private static XNamespace wa = "http://schemas.microsoft.com/windowsazure";
 
        /// <summary>
        /// The operation status values from PollGetOperationStatus.
        /// </summary>
        private enum OperationStatus
        {
            InProgress,
            Failed,
            Succeeded,
            TimedOut
        }
 
        /// <summary>
        /// Gets or sets the management certificate for subscription access.
        /// </summary>
        private static X509Certificate2 ManagementCertificate { get; set; }
 
        static void Main(string[] args)
        {
            try
            {
                ManagementCertificate = GetStoreCertificate(ManagementThumbprint);
 
                // Add a certificate from a particular PFX file in the users
                // documents folder:
                string certificatePath = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                    PfxFile);
                string certificateData = Convert.ToBase64String(
                    File.ReadAllBytes(certificatePath));
 
                Console.Write("Enter the password for {0}: ", PfxFile);
                string pfxPassword = Console.ReadLine();
 
                string requestId = AddCertificate(
                    ServiceName,
                    certificateData,
                    pfxPassword);
                Console.WriteLine(
                    "Called Add Certificate operation: requestId {0}",
                    requestId);
 
                // Loop on Get Operation Status for result of add certificate
                OperationResult result = PollGetOperationStatus(
                    requestId,
                    pollIntervalSeconds: 20,
                    timeoutSeconds: 180);
                DisplayOperationResult(requestId, result);
 
                // Display the certificates for the hosted service.
                XElement certificates = ListCertificates(ServiceName);
                Console.WriteLine(
                    "Certificates for Hosted Service {0}:{1}{2}",
                    ServiceName,
                    Environment.NewLine,
                    certificates.ToString(SaveOptions.OmitDuplicateNamespaces));
                
                // Now delete the added certificate
                requestId = DeleteCertificate(
                    ServiceName,
                    "sha1",
                    CertificateThumbprint);
                Console.WriteLine(
                    "Called Delete Certificate operation: requestId {0}",
                    requestId);
 
                // Loop on Get Operation Status for result of delete certificate
                result = PollGetOperationStatus(
                    requestId,
                    pollIntervalSeconds: 20,
                    timeoutSeconds: 180);
                DisplayOperationResult(requestId, result);
 
                // Display the certificates for the hosted service.
                certificates = ListCertificates(ServiceName);
                Console.WriteLine(
                    "Certificates for Hosted Service {0}:{1}{2}",
                    ServiceName,
                    Environment.NewLine,
                    certificates.ToString(SaveOptions.OmitDuplicateNamespaces));
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception caught in Main:");
                Console.WriteLine(ex.Message);
            }
 
            Console.Write("Press any key to continue:");
            Console.ReadKey();
        }
 
        private static void DisplayOperationResult(
            string requestId, 
            OperationResult result)
        {
            switch (result.Status)
            {
                case OperationStatus.TimedOut:
                    Console.WriteLine(
                        "Poll of Get Operation Status timed out: " +
                        "Operation {0} is still in progress after {1} seconds.",
                        requestId,
                        (int)result.RunningTime.TotalSeconds);
                    break;
 
                case OperationStatus.Failed:
                    Console.WriteLine(
                        "Failed: Operation {0} failed after " +
                        "{1} seconds with status {2} ({3}) - {4}: {5}",
                        requestId,
                        (int)result.RunningTime.TotalSeconds,
                        (int)result.StatusCode,
                        result.StatusCode,
                        result.Code,
                        result.Message);
                    break;
 
                case OperationStatus.Succeeded:
                    Console.WriteLine(
                        "Succeeded: Operation {0} completed " +
                        "after {1} seconds with status {2} ({3})",
                        requestId,
                        (int)result.RunningTime.TotalSeconds,
                        (int)result.StatusCode,
                        result.StatusCode);
                    break;
            }
        }
 
        /// <summary>
        /// Calls the asynchronous Add Certificate operation in the Service 
        /// Management REST API to add a certificate to a hosted service. 
        /// Use the returned request ID value with the Get Operation Status 
        /// operation to get the final result of this operation.
        /// </summary>
        /// <param name="serviceName">The DNS prefix name of the hosted service to add the certificate to.</param>
        /// <param name="certificateData">The base-64 encoded contents of the .PFX file containing the certificate data.</param>
        /// <param name="password">The password to access the .PFX certificate data.</param>
        /// <returns>The request ID for use with Get Operation Status.</returns>
        private static string AddCertificate(
            string serviceName,
            string certificateData,
            string password)
        {
            string uriFormat = "https://management.core.windows.net/{0}" +
                "/services/hostedservices/{1}/certificates";
            Uri uri = new Uri(String.Format(uriFormat, SubscriptionId, serviceName));
 
            // Create the request XML document
            XDocument requestBody = new XDocument(
                new XDeclaration("1.0", "UTF-8", "no"),
                new XElement(
                    wa + "CertificateFile",
                    new XElement(wa + "Data", certificateData),
                    new XElement(wa + "CertificateFormat", "pfx"),
                    new XElement(wa + "Password", password)));
 
            XDocument responseBody;
            return InvokeRequest(
                uri, "POST", HttpStatusCode.Accepted, requestBody, out responseBody);
        }
 
        /// <summary>
        /// Calls the asynchronous Delete Certificate operation in the Service 
        /// Management REST API to remove a certificate from a hosted service. 
        /// Use the returned request ID value with the Get Operation Status 
        /// operation to get the final result of this operation.
        /// </summary>
        /// <param name="serviceName">The DNS prefix name of the hosted service to remove the certificate from.</param>
        /// <param name="algorithm">The algorithm of the certificate to delete, for example, "sha1".</param>
        /// <param name="thumbprint">The thumbprint for the certificate to delete.</param>
        /// <returns>The request ID for use with Get Operation Status.</returns>
        private static string DeleteCertificate(
            string serviceName,
            string algorithm,
            string thumbprint)
        {
            string uriFormat = "https://management.core.windows.net/{0}" +
                    "/services/hostedservices/{1}/certificates/{2}-{3}";
            Uri uri = new Uri(String.Format(
                uriFormat, SubscriptionId, serviceName, algorithm, thumbprint));
 
            XDocument responseBody;
            return InvokeRequest(
                uri, "DELETE", HttpStatusCode.Accepted, null, out responseBody);
        }
 
        /// <summary>
        /// Calls the List Certificates operation in the Service Management 
        /// REST API for the specified subscription and hosted service, and 
        /// returns the Certificates XML element from the response.
        /// </summary>
        /// <param name="serviceName">The DNS prefix name of the hosted service to list certificates for.</param>
        /// <returns>The HostedServices XML element from the response.</returns>
        private static XElement ListCertificates(
            string serviceName)
        {
            string uriFormat = "https://management.core.windows.net/{0}" +
                "/services/hostedservices/{1}/certificates";
            Uri uri = new Uri(String.Format(uriFormat, SubscriptionId, serviceName));
            XDocument responseBody;
            InvokeRequest(uri, "GET", HttpStatusCode.OK, null, out responseBody);
            return responseBody.Element(wa + "Certificates");
        }
 
        /// <summary>
        /// Calls the Get Operation Status operation in the Service 
        /// Management REST API for the specified subscription and requestId 
        /// and returns the Operation XML element from the response.
        /// </summary>
        /// <param name="requestId">The requestId of the operation to track.</param>
        /// <returns>The Operation XML element from the response.</returns>
        private static XElement GetOperationStatus(
            string requestId)
        {
            string uriFormat = "https://management.core.windows.net/{0}" +
                "/operations/{1}";
            Uri uri = new Uri(String.Format(uriFormat, SubscriptionId, requestId));
            XDocument responseBody;
            InvokeRequest(uri, "GET", HttpStatusCode.OK, null, out responseBody);
            return responseBody.Element(wa + "Operation");
        }
 
        /// <summary>
        /// The results from PollGetOperationStatus are passed in this struct.
        /// </summary>
        private struct OperationResult
        {
            // The status: InProgress, Failed, Succeeded, or TimedOut.
            public OperationStatus Status { get; set; }
 
            // The http status code of the requestId operation, if any.
            public HttpStatusCode StatusCode { get; set; }
 
            // The approximate running time for PollGetOperationStatus.
            public TimeSpan RunningTime { get; set; }
 
            // The error code for the failed operation.
            public string Code { get; set; }
 
            // The message for the failed operation.
            public string Message { get; set; }
        }
 
        /// <summary>
        /// Polls Get Operation Status for the operation specified by requestId
        /// every pollIntervalSeconds until timeoutSeconds have passed or the
        /// operation has returned a Failed or Succeeded status. 
        /// </summary>
        /// <param name="requestId">The requestId of the operation to get status for.</param>
        /// <param name="pollIntervalSeconds">The interval between calls to Get Operation Status.</param>
        /// <param name="timeoutSeconds">The maximum number of seconds to poll.</param>
        /// <returns>An OperationResult structure with status or error information.</returns>
        private static OperationResult PollGetOperationStatus(
            string requestId,
            int pollIntervalSeconds,
            int timeoutSeconds)
        {
            OperationResult result = new OperationResult();
            DateTime beginPollTime = DateTime.UtcNow;
            TimeSpan pollInterval = new TimeSpan(0, 0, pollIntervalSeconds);
            DateTime endPollTime = beginPollTime + new TimeSpan(0, 0, timeoutSeconds);
 
            bool done = false;
            while (!done)
            {
                XElement operation = GetOperationStatus(requestId);
                result.RunningTime = DateTime.UtcNow - beginPollTime;
                try
                {
                    // Turn the Status string into an OperationStatus value
                    result.Status = (OperationStatus)Enum.Parse(
                        typeof(OperationStatus),
                        operation.Element(wa + "Status").Value);
                }
                catch (Exception e)
                {
                    throw new ApplicationException(string.Format(
                        "Get Operation Status {0} returned unexpected status: {1}{2}",
                        requestId,
                        Environment.NewLine,
                        operation.ToString(SaveOptions.OmitDuplicateNamespaces)),
                        e);
                }
 
                switch (result.Status)
                {
                    case OperationStatus.InProgress:
                        Console.WriteLine(
                            "In progress for {0} seconds",
                            (int)result.RunningTime.TotalSeconds);
                        Thread.Sleep((int)pollInterval.TotalMilliseconds);
                        break;
 
                    case OperationStatus.Failed:
                        result.StatusCode = (HttpStatusCode)Convert.ToInt32(
                            operation.Element(wa + "HttpStatusCode").Value);
                        XElement error = operation.Element(wa + "Error");
                        result.Code = error.Element(wa + "Code").Value;
                        result.Message = error.Element(wa + "Message").Value;
                        done = true;
                        break;
 
                    case OperationStatus.Succeeded:
                        result.StatusCode = (HttpStatusCode)Convert.ToInt32(
                            operation.Element(wa + "HttpStatusCode").Value);
                        done = true;
                        break;
                }
 
                if (!done && DateTime.UtcNow > endPollTime)
                {
                    result.Status = OperationStatus.TimedOut;
                    done = true;
                }
            }
 
            return result;
        }
 
        /// <summary>
        /// Gets the certificate matching the thumbprint from the local store.
        /// Throws an ArgumentException if a matching certificate is not found.
        /// </summary>
        /// <param name="thumbprint">The thumbprint of the certificate to find.</param>
        /// <returns>The certificate with the specified thumbprint.</returns>
        private static X509Certificate2 GetStoreCertificate(string thumbprint)
        {
            List<StoreLocation> locations = new List<StoreLocation> 
            { 
                StoreLocation.CurrentUser, 
                StoreLocation.LocalMachine 
            };
 
            foreach (var location in locations)
            {
                X509Store store = new X509Store("My", location);
                try
                {
                    store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
                    X509Certificate2Collection certificates = store.Certificates.Find(
                        X509FindType.FindByThumbprint, thumbprint, false);
                    if (certificates.Count == 1)
                    {
                        return certificates[0];
                    }
                }
                finally
                {
                    store.Close();
                }
            }
 
            throw new ArgumentException(string.Format(
                "A Certificate with thumbprint '{0}' could not be located.",
                thumbprint));
        }
 
        /// <summary>
        /// A helper function to invoke a Service Management REST API operation.
        /// Throws an ApplicationException on unexpected status code results.
        /// </summary>
        /// <param name="uri">The URI of the operation to invoke using a web request.</param>
        /// <param name="method">The method of the web request, GET, PUT, POST, or DELETE.</param>
        /// <param name="expectedCode">The expected status code.</param>
        /// <param name="requestBody">The XML body to send with the web request. Use null to send no request body.</param>
        /// <param name="responseBody">The XML body returned by the request, if any.</param>
        /// <returns>The requestId returned by the operation.</returns>
        private static string InvokeRequest(
            Uri uri,
            string method,
            HttpStatusCode expectedCode,
            XDocument requestBody,
            out XDocument responseBody)
        {
            responseBody = null;
            string requestId = String.Empty;
 
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
            request.Method = method;
            request.Headers.Add("x-ms-Version", XMsVersion);
            request.ClientCertificates.Add(ManagementCertificate);
            request.ContentType = "application/xml";
 
            if (requestBody != null)
            {
                using (Stream requestStream = request.GetRequestStream())
                {
                    using (StreamWriter streamWriter = new StreamWriter(
                        requestStream, System.Text.UTF8Encoding.UTF8))
                    {
                        requestBody.Save(streamWriter, SaveOptions.DisableFormatting);
                    }
                }
            }
 
            HttpWebResponse response;
            HttpStatusCode statusCode = HttpStatusCode.Unused;
            try
            {
                response = (HttpWebResponse)request.GetResponse();
            }
            catch (WebException ex)
            {
                // GetResponse throws a WebException for 4XX and 5XX status codes
                response = (HttpWebResponse)ex.Response;
            }
 
            try
            {
                statusCode = response.StatusCode;
                if (response.ContentLength > 0)
                {
                    using (XmlReader reader = XmlReader.Create(response.GetResponseStream()))
                    {
                        responseBody = XDocument.Load(reader);
                    }
                }
 
                if (response.Headers != null)
                {
                    requestId = response.Headers["x-ms-request-id"];
                }
            }
            finally
            {
                response.Close();
            }
 
            if (!statusCode.Equals(expectedCode))
            {
                throw new ApplicationException(string.Format(
                    "Call to {0} returned an error:{1}Status Code: {2} ({3}):{1}{4}",
                    uri.ToString(),
                    Environment.NewLine,
                    (int)statusCode,
                    statusCode,
                    responseBody.ToString(SaveOptions.OmitDuplicateNamespaces)));
            }
 
            return requestId;
        }
    }
}

以下示例输出显示已添加到云服务中的证书,然后在删除该证书后显示云服务没有任何证书:

Enter the password for hostedservicecertificate.pfx: ********
Called Add Certificate operation: requestId fdcf42761fb1424688a5968aa38811d7
In progress for 0 seconds
Succeeded: Operation fdcf42761fb1424688a5968aa38811d7 completed after 21 seconds with status 200 (OK)
Certificates for Hosted Service MyHostedService1:
<Certificates xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Certificate>
    <CertificateUrl>https://management.core.windows.net/01234567-89ab-cdef-0123-456789abcdef/services/hostedservices/MyHostedService1/certificates/sha1-2EA90CBB65EFCF71C92F55363954A16B87941ECD</CertificateUrl>
    <Thumbprint>2EA90CBB65EFCF71C92F55363954A16B87941ECD</Thumbprint>
    <ThumbprintAlgorithm>sha1</ThumbprintAlgorithm>
    <Data>MIIDIDCCAgygAwIBAgIQFacJqSCsGKVGE19GKlrEejAJBgUrDgMCHQUAMCMxITAfBgNVBAMTGGhvc3RlZHNlcnZpY2VjZXJ0aWZpY2F0ZTAeFw0xMTExMTAwMDM3NDRaFw0zOTEyMzEyMzU5NTlaMCMxITAfBgNVBAMTGGhvc3RlZHNlcnZpY2VjZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM94zedfRaAcpOESoStDBM/r18qdOI7HFawK+8sd+atW93L+pJgUjmEYgbHsBET2YZRTWHV2l6HkV7CRnSgTMQ/0SrIsGj+l1BG5Xncdp5Do9dbpHOQmZYVB3t3l0BcFgj3DP+atNXWctUpjdyDJB+USZJB7o0gz3esmyxdD1HaFBu1LW7GfhWHDmC0+QERdoKxAvVKY1wuvCxY1/LdCno6ZMV95l5xJ5jzf/itRo0A9wD5tlcR7bJL7Xp45REKZoaVwxCIooL8fC427LQf2EZbwjhU3kqPOyQ40vNTB+ksJneXqXjhh7Hefond9fFe6O7mwGVfbqOsbFWJsrTA7b40CAwEAAaNYMFYwVAYDVR0BBE0wS4AQMezArIE9mdwqywnNC9Y/NaElMCMxITAfBgNVBAMTGGhvc3RlZHNlcnZpY2VjZXJ0aWZpY2F0ZYIQFacJqSCsGKVGE19GKlrEejAJBgUrDgMCHQUAA4IBAQA0XehZ43Yt/u/NlOSYOkGhCeomndZbBcijGH9fo39OiMPwN1BOY1Ch1YmlTt60o/1u1Lg7oxx9+NfE4O2x2xqBK+SIT/W4gtowjmwFg+dRu0qRCYcJL1HaQWGoRbkZrJHNOKsBVUWJbSKyOtM/MZ2v5eZ2q2imDLNMnIPY6YaeP9s4lLhcu53iuzkHf1JvsmNkvI7XQkCw2W/COu8ndcXmTrhc1btz+j3r6G9siGeRQ+xDV394GIAtTZgszefJXVkjiYlHczUmr0ZPKWh3vA/RTyrcQfDVH0QBZ9CMYNhhI1PIJOPAQ3X5YsYQwah9pbYV4mIXaJKld+eNsEFt3Zo8</Data>
  </Certificate>
</Certificates>
Called Delete Certificate operation: requestId e480c3ffab2a4b7a840730200f004130
Succeeded: Operation e480c3ffab2a4b7a840730200f004130 completed after 0 seconds with status 200 (OK)
Certificates for Hosted Service MyHostedService1:
<Certificates xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
Press any key to continue:

显示:
© 2015 Microsoft