Dan Griffin's Blog

Comments on security, PKI, smart cards, cryptography, and entrepreneurship.

Now all of the project landing pages for the Samples 2009 group on CodePlex have nice “inline” screenshots. That way, if you’re looking for reusable XAML, you know what you can get from these projects. Here are the five project URLs:

Permalink | Comments (0)

Check out the EC2 Bootstrapper project site on CodePlex.

Permalink | Comments (0)

The latest EC2 Bootstrapper code and developer specification has been added to the CodePlex site for that project. The specification document includes prototype screenshots as well as the latest graphic design mock-ups (integration of which is pending).

Permalink | Comments (0)

I’ve decided to change the name of this project from EC2 Console to EC2 Bootstrapper. Why? Well, there are several “EC2 Console” projects out there. But we’re addressing a problem that no one else has - how to remotely (and securely) install software to a Windows machine on EC2 without having to logon to that machine and do it manually (for example, emailing the package to yourself, or posting it somewhere on the internet). That’s the bootstrapping issue, and right now, it’s the biggest hurdle for encouraging ASP.NET developer adoption of that platform, and making this kind of deployment easier than it is on Linux (where the most common approach would just be a question of bootstrapping SSH).

We’ll still have the usual management console basics, including listing, starting, and stopping machines. But “one-click” EC2 Windows application bootstrapping is the major contribution that this is making to the world.

To that end, the first code drop is available here (Codeplex). That drop includes the following things.

First, there’s a script that will run once (on first boot, then remove itself) to initialize the EC2 AMI (Amazon Machine Instance) with a self-signed server SSL certificate. The script uses SelfSSL.exe from the IIS 6.0 resource kit. That tool turns out the be a god-send: creating a self-signed certificate is easy enough with makecert.exe, but the interfaces for automatically configuring IIS with proper SSL defaults aren’t well documented.

The script is part of the solution to another problem as well. Namely, once the new AMI is running, and a new SSL cert is installed, how do we download that cert so the client can trust it? There are probably a number of ways to do that, but a convenient one is to export the cert (the public part; not the private key) on the server (using certutil.exe), copy the cert file to a known location in the default web site, and let the client grab it via HTTP.

Interesting aside about getting what was originally a .cer file to be served by IIS. In short, I couldn’t get it to work (i.e., IIS acted like the file didn’t exist, even though you could see it in the virtual dir listing in the MMC snap-in), even after I realized that there was no registered MIME handler for that extension. But I noticed that there is a handler for .crt, which is equivalent to .cer from a PKI plumbing perspective. Using the .crt extension fixed things. Don’t know why I couldn’t get a .cer MIME handler to work.

In addition to the script, the Codeplex drop includes some fun code. The most important piece is a web service which will be configured to listen on a high port, require Windows authentication, and allow (maybe require; not sure yet) SSL. Clients that can authenticate to the service will be able to upload an MSI file and have it installed on the AMI.

In a nutshell, creating an AMI that automatically starts up with the script and secure web service is our EC2 bootstrapping story.

A few notes about that web service. First, since we can’t count on the Network Service account being able to install an MSI, the service end point routine starts by impersonating the caller. Then it reads in the encoded MSI file data, decodes it, writes it to a temporary file, runs msiexec.exe in silent mode, waits for the result, and returns it (after un-impersonating). Even though we’re impersonating and requiring valid credentials, a good enhancement would probably be to explicitly check that the caller is a member of the local administrators group.

In addition to the service, there’s a test client. I ran into two challenges with that. The first was that, since this code is checked in publicly, I didn’t want to hardcode the admin password for my local test server. And, lamely, .NET doesn’t include a built-in credential prompt dialog. Instead, you have to either write your own or P/Invoke CredUI. I chose the latter approach, but found a P/Invoke signature for CredUIPromptForCredentials on the web that had at least a couple of bugs, not the least of which that it didn’t explicitly specify whether it was using the Ansi or Unicode version of that Win32 API. I had the quickest luck getting the “A” version to work - shouldn’t matter unless you’ve got a user name or password with characters that don’t round-trip correctly (which would be truly brave).

One more comment about CredUIPromptForCredentialsA (or W). The user name and password parameters are actually “In” as well as “Out”. In other words, the API lets the caller pre-populate those fields. Thus, if the marshaller finds garbage in the input string buffers, you’ll see weird characters in the edit fields when the dialog pops up. This is another issue not addressed by P/Invoke wrappers you may find on the web. The fix is to start with a String of the proper length initialized to NULL chars (presumably just at the beginning, although I didn’t try that potential optimization), then build the in/out StringBuilder from that.

The second test client challenge was in figuring out how to get Visual Studio to let me add a web service reference to a console application. In other words, I didn’t want to have to run wsdl.exe myself! The trick was to run the web service project without debugging, so I could leave it running while adjusting the solution/project settings for the console application. Then, under the console project in Solution Explorer, right-click on References | Add service reference | Advanced | Add web reference.

Permalink | Comments (0)

Check out the dev spec posted here (for this project).

Most notable about the spec: we’ve got a plan for how to bootstrap a Windows AMI (Amazon Machine Instance) in such a way that we can have it immediately (but securely) install an arbitrary MSI package on boot. This is going to be a cool tool!

Permalink | Comments (1)

Regarding the EC2 Console sample (Windows Presentation Foundation) application, here’s the tentative feature list:

  1. In order to maintain the list of EC2 machine instances, and the current status of each, auto-refresh the client GUI at a preset interval. This applies when waiting for machines to shutdown and start-up, and waiting for volumes to be created. That way user doesn’t have to keep on hitting Refresh.
  2. Mouse pointer needs to indicate when something’s happening. Current EC2 console is bad at this, and also not very responsive.
  3. Filter AMIs for Windows-only by default
  4. Help matching on Availability zones, e.g. for instances and volumes. Windows is currently only available in 1B, so presumably always pick that as the default. When creating a new Volume, first ask if it applies to a specific instance. If it does, create the Vol in the same zone and then automatically attach it.
  5. Auto-configure to allow TermSrv from the IP address of the current host. Probably should handle dynamic IP address updates somehow, since many people will try to use this via cable broadband connections.
  6. Offer a shortcut link to shell exec a TermSrv window to the machine in question
  7. While decrypting the default password via the current AWS Console, IE always times out and repeatedly throws an annoying dialog. Find a way to decrypt the PEM file via Win32.
  8. Heartbeat on public DNS and Elastic IP (if bound) for each machine instance

Other feature requests and feedback is welcome. In the meantime, I’ll work on the developer specification.

Permalink | Comments (0)

In ramping up for this project, the first thing to do was to get a Windows Server instance running on EC2 and deploy a test web application to it. I figured that that experience would be typical of what most developers will need to do as they experiment with this cloud computing platform. In fact, it was easier than I thought it would be. Here are my “lab notes”:

I started with the existing AWS Management Console (I’d signed up for an account previously; you’ll need one in order to try any of this). The first step was to create a new machine Instance. I used the public one named “ami-45bf582c,” which is basically Windows Server 2003. I selected the medium CPU load, just because I wanted reasonable responsiveness while experimenting with things.

Next, I created and attached an “Elastic Block Store” volume. In other words, a persistent drive. Note that anything you save on a non-EBS drive is gone forever once the virtual host reboots. I actually ended up not needing the EBS volume for this testing, but it was comforting to know it was there in case, in the middle of my work, I decided I wanted to save something!

If you do create an EBS volume, be sure it’s in the same zone as the machine instance that you want to attach it to (currently, Windows machines can only run in zone us-east-1b, but that’s not the default zone when creating a new volume). Also, the current version of the AWS console has a bug in selecting the target instance when attaching a volume. The available instance (I had only one) doesn’t appear, even though it is in the same zone. Just hit okay on the dialog anyway; the volume will attach to the default instance (again, not sure what will happen if you’ve got more than one).

A few additional notes about preparing the Windows instance before deploying a test website:

  1. A static IP can be allocated and bound to the machine for testing, but that’s not required for this test. The public DNS name assigned to the instance is fine.
  2. Enable RDP for the machine group in question via the AWS console. There’s a built-in setting for this (called “RDP”), but it’s filtered (blocked) by default. I also opened up HTTP this way.
  3. Once I’d connected to the test machine instance via RDP, I removed the Windows Server 2003 IE hardening settings via appwiz.cpl in order to have a more functional Internet Explorer. That’s something you wouldn’t want to do for a production deployment.
  4. Also using appwiz.cpl, I installed the ASP.NET feature under Application Server in Windows components. That may not be a required step, though.
  5. In the IIS Management MMC snap-in, I enabled all of the web service extensions. Again, for a production deployment, you’d want to do this only selectively.

Now, what about the test web application? Visual Studio has a great feature for deploying web applications, namely, the Web Setup Project type. There’s a reasonable introduction to that feature here. I decided to use that approach for my test deployment.

However, once the MSI CAB built has been built for the test web site, there’s still the question of how to get it onto the EC2 machine instance. The ports I’d opened - RDP and HTTP - aren’t much help when it comes to copying files.

To digress briefly, I decided to experiment with using SMB (i.e., file shares) to copy the web site installer. Thus, I returned to the AWS console security group settings and opened up a few additional ports: 135, 139, and 445. To my chagrin, that doesn’t work; Amazon still blocks them:

>nmap.exe -v  -PN X.X.X.X -p T:80,135,139,445,3389

Starting Nmap 4.68 ( http://nmap.org ) at 2009-02-04 14:35 Pacific Standard Time
Initiating Parallel DNS resolution of 1 host. at 14:35
Completed Parallel DNS resolution of 1 host. at 14:35, 6.50s elapsed
Initiating SYN Stealth Scan at 14:35
Scanning ABC.compute-1.amazonaws.com (X.X.X.X) [5 ports]
Discovered open port 80/tcp on X.X.X.X
Discovered open port 3389/tcp on X.X.X.X
Completed SYN Stealth Scan at 14:35, 2.58s elapsed (5 total ports)
Host ABC.compute-1.amazonaws.com (X.X.X.X) appears to be up … good
.
Interesting ports on ABC.compute-1.amazonaws.com (X.X.X.X):
PORT     STATE    SERVICE
80/tcp   open     http
135/tcp  filtered msrpc
139/tcp  filtered netbios-ssn
445/tcp  filtered microsoft-ds
3389/tcp open     ms-term-serv

What to do instead? I took the easy way out: zip up the web installer MSI, email it to myself, and open it on the EC2 instance. Note - this is one reason that you’d need to disable IE hardening for testing purposes, otherwise you probably wouldn’t be able to logon to your webmail site.

What to do for deployment into production? Amazon suggests using FTP or FrontPage Server Extensions. I wouldn’t recommend the former, since the password is sent cleartext, unless you’re piping it through (a Windows build of) SSH. Regarding FPSE, I tried installing them via Add/Remove Programs and got an error about missing installation media. Thus, the solution will be some combination of scripting and keeping certain tools and media on an EBS volume.

In any case, once I’d installed the test web site via the email attachment, it worked fine the first time around, including remotely via the public DNS name.

Permalink | Comments (0)

Two projects in this series have already been introduced: Web Password Storage and Bio Approval Workflow. The next one up is EC2 Console.

The purpose of the EC2 Console, like the other ones, is to demonstrate an attractive (WPF-based), novel, and useful application on Windows. In this case, we chose as our vehicle a helpful control panel for Windows developers who are new to cloud computing and would like to experiment with Windows Server, ASP.NET, and MS SQL on Amazon’s EC2 platform.

As it happens, Amazon already has an EC2 console (currently in Beta). But we’re going to differentiate ourselves from that in two ways. First, our EC2 Console will be specific to developers targetting Windows, and we can automate many administration tasks given that assumption. Second, our console (again, a WPF client app) will exhibit the kind of superior usability that is very difficult to achieve via the browser.

Permalink | Comments (0)