Windows Azure, SSL, Self-Signed Certificate and Annoying HTTPS Input Endpoint Does Not Contain Private Key Error
On 2/4/2012 12:23 AM by Tugberk
Deploying a Web Role with HTTPS Endpoint enabled with Self-Signed Certificate and a annoying problem of HTTPS input endpoint does not contain private key
While I was trying out the Windows Azure features yesterday, I had a deployment problem. The case was to deploying SSL enabled web role. Let’s walk through the steps I have taken. Since it was a try out, I decided to create a self-signed certificate instead of buying one. The case of how I created the self-signed certificate was fairly simple. I opened up the Visual Studio Command Prompt (2010) and cd to directory path where I would like to put the certificate file I was about to create. Then, I used the following makecert command line utility to create the certificate. Here is the code I used: makecert -sky exchange -r -n "CN=TugberkUgurlu.Com" -pe -a sha1 -len 2048 -ss My "Azure.TugberkUgurlu.Com.cer" I had my .cer file under c:\Azure\Certs directory. Also, I executed the following script on PowerShell console and I saw the certificate listed there.
dir cert:\CurrentUser\My
In order to upload the certificate to windows azure, I needed to export the certificate from .cer file to .pfx. Here where things get messy. I used the followig powershell script to create one but I was about to realize that it was the wrong decision. We'll see why in a minute. $c = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("c:\azure\certs\Azure.TugberkUgurlu.Com.cer") $bytes = $c.Export("Pfx","password") [System.IO.File]::WriteAllBytes("c:\azure\certs\Azure.TugberkUgurlu.Com.pfx", $bytes) The next step was to deploy this .pfx file to Certificates store of my windows azure hosted service. In order to complate this challange, I went to Windows Azure portal, navigated to my hosted service. Right click on the blue Certificate folder (I think it is a folder icon but not sure exactly what it is) and click Add Certificate: It poped up a dialog box for me to upload that certificate file. I completed the steps and there it was. I had the certificate deployed on my hosted service. Finally, I was done setting things up and I can jump right to my application. Wait, I wasn't done yet complately! I had to set things up at the application level so that I could hook it up to that certificate I had just uploded. At that stage, first thing I did was to grab the thumbprint of the certificate. I ran the following PowerShell command to grab the thumbprint of the certificate: (New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("c:\azure\certs\Azure.TugberkUgurlu.Com.cer")).Thumbprint With that thumbprint, I went to my project and added the following code inside ServiceConfiguration.Clound.cscfg and ServiceConfiguration.Local.cscfg under Role node: <Certificates> <Certificate name="Azure.TugberkUgurlu.Com" thumbprint="AAD5DDD0CA9B4D3CFEF1652130142020770B8BDF" thumbprintAlgorithm="sha1"/> </Certificates> The ServiceDefinition.csdef file needed a little more touch than the configuration files. Here is the complate csdef file after the set-up: <ServiceDefinition name="HttpsEnabledCloudProject" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition"> <WebRole name="MvcWebRole1" vmsize="Small"> <Sites> <Site name="Web"> <Bindings> <Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="azure.tugberkugurlu.com" /> <Binding name="HttpsIn" endpointName="HttpsIn" hostHeader="azure.tugberkugurlu.com" /> </Bindings> </Site> </Sites> <Endpoints> <InputEndpoint name="Endpoint1" protocol="http" port="80" /> <InputEndpoint name="HttpsIn" protocol="https" port="443" certificate="Azure.TugberkUgurlu.Com" /> </Endpoints> <Imports> <Import moduleName="Diagnostics" /> </Imports> <Certificates> <Certificate name="Azure.TugberkUgurlu.Com" storeLocation="LocalMachine" storeName="My" /> </Certificates> </WebRole> </ServiceDefinition> Everything looked right at that point but got an ugly error message telling me that my deployment had been failed:
After a couple of searched on the internet, I ended up checking the private key of my certificate and here is the result: That looked awkward and might be the problem. Then I grabed the certificate from the certificate store and check the private key. That was the evidence that it was the problem: At that point, I created the .pfx file from the certificate in my certificate store with following code: $cert = (get-item cert:\CurrentUser\My\AAD5DDD0CA9B4D3CFEF1652130142020770B8BDF) $bytes = $cert.Export("Pfx","password") [System.IO.File]::WriteAllBytes("c:\azure\certs\Azure.TugberkUgurlu.Com_2.pfx", $bytes) At last, I deleted the certificate which was under my hosted service and reuploaded the new one I had just created. Lastly, I ran the publish process again without changing anything inside my code, configuration or service definition files and I suceedded! Here is the SSL enabled application running in the cloud: Please comment if you have the same problem as me so that I won't feel lonely in this small World:) How to Use Windows Azure Blob Storage Service With ASP.NET MVC Web Application
0
Comments
On 1/18/2012 9:17 AM by Tugberk
This blog post provides a Windows Azure Blob Storage example which walks you through on how to use Blob Storage service with ASP.NET MVC.
I have been digging into Windows Azure more and more lately. I wish that it would be supported in Turkey but anyway, emulator is my cloud for now One feature of Windows Azure platform which I will be using is Blob Storage. Blob storage enables you to store your unstructured data (like pictures, word docs, excel file, etc.) inside Windows Azure servers and access them over HTTP or HTTPS. With Windows Azure .Net SDK, you have full control over your blobs and program against that easily. How? Let’s see.
First thing is first. We need an ASP.NET MVC project to simulate this (but it doesn’t have to be ASP.NET MVC project). We have two options to make our application azure-cloudy: Directly Create a Cloud Application Inside the new project dialog box on Visual Studio, choose Windows Azure Project as indicated below: When you hit OK, you will see a dialog as below: This dialog box is like a open buffet, you can choose which project you need for your application here. But we will choose ASP.NET MVC 3 Web Role and then hit OK: Then we will see a dialog box which is owned by ASP.NET MVC. From now on everything is same like it is a standard ASP.NET MVC project. Make Your Application Azure-Cloudy Later Assuming that we have an existing ASP.NET MVC application and we want to run this application on Windows Azure. What we need to do is to right click on our project and choose "Add Windows Azure Deployment Project Option" as below: Either way, our solution will look something like this: Configure to Work With Blob Storage We have a few steps to make before we can start developing. In a real world scenario, you need a Windows Azure storage account to use the blob storage service and you can create this account from Windows Azure Management Portal. After you configure your account, you will have your access keys to that storage account which you will need on your development process. One thing to mention before going further is that you will be able to access your files through HTTP or HTTPS as motioned before and the URL for your blobs will look like this: http://<storage account>.blob.core.windows.net/<container>/<blob> There is a way to change this so that you can use your own domain. In our example, we will be reaching out our blobs through localhost. we will get to that later in this post. In order to develop locally with emulator, we do not need a storage account which means that we don’t need access keys. In order to configure it so, right click on the web role file and choose Properties. This action will brings up the properties windows. From there, go to Settings tab and click add settings and on the new created node, select Connection String as Type and click "..." which stands right hand side. This action will also open up a new window for you and this is where you configure your storage account. But we will choose "Use the Windows Azure storage emulator" option and give this configuration a new friendly name: Those actions are not required but viewed as a best practice while working windows azure cloud projects. Also, you can use Windows Azure Storage and run your application inside your own servers. It is totally fine. So, in that case you won’t need a cloud project. What .Net SDK provides is a wrapper around Windows Azure REST APIs which makes it easy to program against. Now we are all set and finally we can write some code. First of all, we need two additional libraries to develop against Windows Azure with .Net:
Those two will give us everything we need. For the sake of simplicity, I created a simple project which uploads images through Windows Azure Storage service and list those images on a page. In order to do that so, I created a service class (which is a standard class, nothing further than that) called MyBlobStorageService. Let’s see the code first:
public class MyBlobStorageService { public CloudBlobContainer GetCloudBlobContainer() { // Retrieve storage account from connection-string CloudStorageAccount storageAccount = CloudStorageAccount.Parse( RoleEnvironment.GetConfigurationSettingValue("StorageConnectionString") ); // Create the blob client CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); // Retrieve a reference to a container CloudBlobContainer blobContainer = blobClient.GetContainerReference("albums"); // Create the container if it doesn't already exist if (blobContainer.CreateIfNotExist()) { blobContainer.SetPermissions( new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob } ); } return blobContainer; } } What this code does it fairly simple. It gets the storage account information form the connection string that we have configured and creates a CloudStorageAccount class according to that. Then, We create a blob storage client (CloudBlobClient) over that storage account. Finally, we create a container (CloudBlobContainer) for our blobs and check if it exists of not. If not, then we simply create it and set the public access permission to it because we will store images inside that container and we want to display those images on our web page. In order to demonstrate this, I have two controller actions. One is for HTTP GET and the other is for HTTP POST. Here is the complete controller code:
public class HomeController : Controller { public MyBlobStorageService _myBlobStorageService = new MyBlobStorageService(); public ActionResult Index() { // Retrieve a reference to a container CloudBlobContainer blobContainer = _myBlobStorageService.GetCloudBlobContainer(); List<string> blobs = new List<string>(); // Loop over blobs within the container and output the URI to each of them foreach (var blobItem in blobContainer.ListBlobs()) blobs.Add(blobItem.Uri.ToString()); return View(blobs); } [HttpPost] [ActionName("index")] public ActionResult Index_post(HttpPostedFileBase fileBase) { if (fileBase.ContentLength > 0) { // Retrieve a reference to a container CloudBlobContainer blobContainer = _myBlobStorageService.GetCloudBlobContainer(); CloudBlob blob = blobContainer.GetBlobReference(fileBase.FileName); // Create or overwrite the "myblob" blob with contents from a local file blob.UploadFromStream(fileBase.InputStream); } return RedirectToAction("index"); } } And the view code is simple as well: @model List<string> @{ ViewBag.Title = "My Cloudy Album"; } <h2>My Cloudy Album</h2> @foreach (var item in Model) { <img src="@item" width="200" height="100" /> } @using (Html.BeginForm("index", "home", FormMethod.Post, new { enctype = "multipart/form-data" })) { <input type="file" name="fileBase" /> <p> <input type="submit" value="Upload" /> </p> } Now we are all set and go to go.
When we hit CTRL + F5, VS will create a cloud deployment package and deploy it to emulator and we will see the emulator starting up: Now we are cloudy! When we choose a picture and upload it, we should be able to see it after we got back. One more thing to prove that we really run inside the emulator is to right click the emulator icon, choose Show Storage Emulator UI: This will bring up the Storage Emulator as below: On the right hand side, there is a reset button. Click it to reset the emulator and go back to your page and refresh. You will see that all the pictures that you have uploaded are gone now. That’s all for now Additional Resources Entity Framework DbContext Generic Repository Implementation Is Now On Nuget and GitHub
2
Comments
On 1/15/2012 10:41 AM by Tugberk
Entity Framework DbContext Generic Repository Implementation Is Now On Nuget and GitHub: PM> Install-Package GenericRepository.EF
Couple of weeks ago, I have done two blog post on Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle and How to Work With Generic Repositories on ASP.NET MVC and Unit Testing Them By Mocking and I have put up the https://github.com/tugberkugurlu/GenericRepoWebApp up on GitHub as well. Now, the Generic Repository implementation has its own project separately: https://github.com/tugberkugurlu/GenericRepository. This is a simple project and has not much inside it but it is nice to have something static so that it can be improved along the way. Here is a brief intro:
I await for your PRs :) ASP.NET MVC Code Review #2 - A Way of Working with Html Select Element (AKA DropDownList) In ASP.NET MVC
0
Comments
On 12/30/2011 4:28 PM by Tugberk
This is the #2 of the series of blog posts which is about some core scenarios on ASP.NET MVC: A Way of Working with Html Select Element (AKA DropDownList) In ASP.NET MVC
This is the #2 of the series of blog posts which is about some core scenarios on ASP.NET MVC. In this one, code review #2, I will try to show you the best way of working with Html Select element (AKA DropDownList) in ASP.NET MVC. Here is the code: Repository Class which generates the dummy data for the demo: public class ProductCategory { public int CategoryId { get; set; } public string CategoryName { get; set; } } public class ProductCategoryRepo { public List<ProductCategory> GetAll() { List<ProductCategory> categories = new List<ProductCategory>(); for (int i = 1; i <= 10; i++) { categories.Add(new ProductCategory { CategoryId = i, CategoryName = string.Format("Category {0}", i) }); } return categories; } } Controller: public class SampleController : Controller { private readonly ProductCategoryRepo productCategoryRepo = new ProductCategoryRepo(); public ActionResult Index() { registerProductCategorySelectListViewBag(); return View(); } private void registerProductCategorySelectListViewBag() { ViewBag.ProductCategorySelectList = productCategoryRepo.GetAll().Select( c => new SelectListItem { Text = c.CategoryName, Value = c.CategoryId.ToString() } ); } } View: @{
ViewBag.Title = "HTML Select List Sample";
}
<h2>HTML Select List Sample</h2>
<p>
<strong>Product Categories:</strong>
</p>
<p>
@Html.DropDownList(
"ProductCategoryId",
(IEnumerable<SelectListItem>)ViewBag.ProductCategorySelectList
)
</p>
Let’s see what it generates for us: Output HTML of Select element: <select id="ProductCategoryId" name="ProductCategoryId"> <option value="1">Category 1</option> <option value="2">Category 2</option> <option value="3">Category 3</option> <option value="4">Category 4</option> <option value="5">Category 5</option> <option value="6">Category 6</option> <option value="7">Category 7</option> <option value="8">Category 8</option> <option value="9">Category 9</option> <option value="10">Category 10</option> </select> Just like what I expected. On the controller, you see that I newed up SelectListItem classes and pass them to the view through the ViewDataDictionary. SelectListItem class works nicely with DropDownList and DropDownListFor Html helpers within ASP.NET MVC as you see inside the view code above. So, don’t try to reinvent the wheel and don’t get into for and foreach loops in order just to create a select element. SelectListItem has been put inside the library just for this purpose and leverage it. |
Connect With MeTagsArchive
Blogroll |




















Comments