As I near deployment of a moderately large-scale ASP.NET 2.0 web application, I'm trying to wrap my head completely around all of the issues related to deployment. One of the questions that keeps boiling up in my mind is how an ASP.NET web application, some of the AJAX stuff, IIS, and SSL all play nice together.
After doing some research online, and even asking some guys that run web sites for a living, I've come to the conclusion that this is definitely something that is best learned by doing. So, I'm going to attempt to setup the whole package on my development machine. I know enough about SSL to know that this won't be a perfect simulation. I'm going to try to generate my own certificate, so I'll just have to pretend like I don't see Firefox telling me that the certificate is not from a trusted source or whatever - if I manage to get that far. Here goes.
The Self-Signed Certificate
When searching for a method to make my own certificate, a couple of methods were commonly suggested on forums and blog articles:
- SelfSSL - part of the IIS Resource Kit
- MakeCert - seems to be bundled with Visual Studio
- MS Certificate Authority.
I decided to try SelfSSL, since it seems to be the easiest at first glance. So, I downloaded and installed the IIS Resource Kit (which claims to be for IIS 6.0, but people ay it works fine on Windows XP / IIS 5.1). I did a custom install and only installed the IIS 6.0 Tools Documentation, SelfSSL, TinyGet, Web Capacity Analysis Tool, and WFetch. The other stuff sounded useful, but I'll probably just forget about it and only use SelfSSL.
After the install finishes, running SelfSSL from the start menu will bring up a command box with the following info and prompt:
Microsoft (R) SelfSSL Version 1.0
Copyright (C) 2003 Microsoft Corporation. All rights reserved.
Installs self-signed SSL certificate into IIS.
SELFSSL [/T] [/N:cn] [/K:key size] [/S:site id] [/P:port]
/T Adds the self-signed certificate to "Trusted Certificates"
list. The local browser will trust the self-signed certificate
if this flag is specified.
/N:cn Specifies the common name of the certificate. The computer
name is used if not specified.
/K:key size Specifies the key length. Default is 1024.
/V:validity days Specifies the validity of the certificate. Default is 7 days.
/S:site id Specifies the id of the site. Default is 1 (Default Site).
/P:port Specifies the SSL port. Default is 443.
/Q Quiet mode. You will not be prompted when SSL settings are
overwritten.
The default behaviour is equivalent with:
selfssl.exe /N:CN=ADAM-IMS /K:1024 /V:7 /S:1 /P:443
C:\Program Files\IIS Resources\SelfSSL>
I decided to be gutsy and try it with all default settings - except to set the validity to 30 days instead of 7.
> selfssl.exe /V:30
> iisreset
Cool beans. Now, if I look at the "Directory Security" tab in IIS for my default web site (or any of the site under that for that matter) I can click "View Certificate" and see the self-signed certificate I've installed. There are some errors displayed about it not being from a Trusted Certificate Authority, but I expected that since I made it myself, and didn't get it from a CA like GeoTrust or Thawte or GoDaddy.
I'll try going to https://localhost now - I have just a dummy page set up there in the Default Site. Ok - two warning dialogs popup. The first, as I expected, told me that the certificate is not signed by a trusted CA. The second warns me that the certificate is for ADAM-IMS, but I am viewing localhost. I want to fix this second one, since Visual Studio usually opens up to localhost when debugging a web application.
> selfssl.exe /N:CN=localhost /V:30
> iisreset
There, that did the trick. Now I just get the first warning.
Testing the App
Cassini, aka the Visual Studio Development Server, does not currently support SSL (and I doubt it will anytime soon). Makes sense - it basically opens up a standard http server on a single port (usually 49587 or something like that). SSL typically runs on port 443 of IIS, separate from the standard http server typically on port 80. That is why most browsers go to port 80 automatically for http:// and go to port 443 automatically for https:// - of course, Microsoft could write Cassini to support SSL, and make some new convention for what ports are what on Cassini, but I don't think they will anytime soon since you can specify in your project settings that you want to debug your web application using IIS anyhow. Cassini is for convenience, but you are getting in pretty deep by the time you are thinking about SSL.
So, I set my web app to run on IIS (at localhost/<project_name> for the application root) and fired it up. Currently, I have to manually switch from http:// to https://, but I'll probably have my Master Page and login page redirect to https:// if a user attempts to connect insecurely.
Things went better than I expected when floating around my application, testing stuff and watching for popup warnings like "This page has encrypted and un-encrypted elements... do you want to display the un-encryted stuff?" I have tried to keep the eventual conversion to secure application in mind, and always follow these conventions:
- When linking to an image, or another page in the web app, I always use either relative urls [e.g. "img/first.png"] or the ASP.NET application relative path [e.g. "~/dynamics/dynamics.aspx" or
ResolveUrl("~/somepage.aspx")] - I always use relative paths in CSS url("...") values
To be continued?
I'll keep messing around with this, and see if anything else pops up.
Useful things I came across in researching this:
blog.coryisakson.com - MakeCert, and redirecting to https://
Scott Guthrie: Enabling SSL on IIS 7.0 using Self-Signed Certificates - incase you have IIS 7.0, things look much easier
Rob Conery: SSL and Development - SelfSSL, by a guy whose blog I read regularly. Odd and cool that his blog would have this tucked away in the archives.