Geeks With Blogs

News This is the *old* blog. The new one is at blog.sixeyed.com
Elton Stoneman
This is the *old* blog. The new one is at blog.sixeyed.com

If you want to use the Azure Resource Management APIs, Service Management APIs or Management Libraries, you'll need a management certificate which authenticates your process with the Azure subscription you're accessing. Chances are you'll already have one or more management certs installed (from Visual Studio or the PowerShell SDK or WebMatrix) with the issuer name Windows Azure Tools:

image

It's a good idea to mint a separate one for your new process, so it's clear what the cert is used for. Creating a new cert is easy with the makecert utility.

This command creates a valid X.509 cert, using SHA1 and a 2048 bit key, installing it to your local certificate store and exporting the public key to a .cer file:

makecert -sky exchange -r -n "CN=my.mgt.app.name" -pe -a sha1 -len 2048 -ss My my-mgmt-app.cer

(See Alice Waddicor's post Generating and using a certificate to authorise Azure Automation for a description of each parameter).

That's the easy part, and you can upload the certificate to your subscription through the Azure Portal, allowing API access to anyone who has the private key for the cert (which you'll need to manage carefully).

If you want to upload the .cer file programtically, I've wrapped it up in a console app on github here: sixeyed/azure-tools/UploadManagementCertificate

The app uses the Microsoft.WindowsAzure.Management.Libraries NuGet package. The upload is easy enough, loading the cert details into ManagementCertificateCreateParameters from an X509Certificate2 object:

var newCertificate = new X509Certificate2(newCertificateCerFilePath); 
var parm = new ManagementCertificateCreateParameters() 
{ 
    Data = newCertificate.RawData, 
    PublicKey = newCertificate.GetPublicKey(), 
    Thumbprint = newCertificate.Thumbprint 
};

And then calling Create on a ManagementClient object - note that the client object throws a CloudException even if the call succeeds and returns the expected 201: Created result (which looks like a bug):

var creds = new CertificateCloudCredentials(subscriptionId, existingCertificate); 
var client = new ManagementClient(creds); 
try 
{ 
    var response = client.ManagementCertificates.Create(parm); 
} 
catch (CloudException ex) 
{ 
    success = ex.Response.StatusCode == HttpStatusCode.Created; 
}

To use the Management SDK and upload a cert, you need to have a management certificate already uploaded to your subscription for the SDK to use, but you can make use of the existing 'Windows Azure Tools' cert you'll have on a dev box. You could have many of those installed, and the only way to check if one is valid for your subscription is to try and use it. It's crude but here's how you find which of the existing certs in your local store is valid for a subscription:

var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser); 
certStore.Open(OpenFlags.ReadOnly); 
var azureCerts = certStore.Certificates.Find(X509FindType.FindByIssuerName, "Windows Azure Tools", false); 
foreach (var cert in azureCerts) 
{ 
    var creds = new CertificateCloudCredentials(subscriptionId, cert); 
    var client = new ManagementClient(creds); 
    try 
    { 
        var v = client.Locations.List(); 
        return cert; 
    } 
    catch (CloudException ex) 
    { } 
}

Incidentally, don't try and do this with PowerShell. You can use the SDK libraries and create the objects and this snippet looks like it should work:

$creds = New-Object -TypeName Microsoft.Azure.CertificateCloudCredentials -ArgumentList $subscription.SubscriptionId, $cert 
$client = New-Object -TypeName "Microsoft.WindowsAzure.Management.ManagementClient, Microsoft.WindowsAzure.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" $creds 
try 
{ 
    #doesn't work - throws 'ManagementClient requires a WebRequestHandler in its HTTP pipeline to work with client certificates.' 
    $locs = [Microsoft.WindowsAzure.Management.LocationOperationsExtensions]::List($client.Locations) 
    $existingThumbprint = $cert.Thumbprint 
} 
catch 
{ 
    #ignore, cert not valid for sub 
}

- but it doesn't. When you run it you'll get an exception -

New-Object : Exception calling ".ctor" with "1" argument(s): "ManagementClient requires a WebRequestHandler in its HTTP pipeline to work with client certificates."'.

Good luck getting past that. When I hit it I went for the console app route...

Posted on Monday, June 29, 2015 12:23 PM github , Azure , tools | Back to top


Comments on this post: How to programmatically upload a new Azure Management Certificate

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Elton Stoneman | Powered by: GeeksWithBlogs.net