Setting EC2 Volume Tags for Cost Tracking

Like many AWS users, our company needs to track our AWS costs by project and client for accounting purposes.  Amazon makes it pretty easy to do this using tags and some settings in the billing console.  In our case, we added a CostCenter tag to each instance and ELB to indicate how to allocate the cost. Because most of our instances have at least two volumes, setting the tags manually for the volumes would have been very tedious and error prone. Therefore, I put together this little Powershell script to do the work for us by copying the CostCenter tag from the instance to all its associated volumes:

$volumes = Get-EC2Volume

Write-Host "Setting cost center tag on " $volumes.Count " volumes"
foreach ($vol in $volumes) {
  $tags = $vol.Attachments | %{$_.InstanceId} | Select-Object -First 1 | Get-EC2Instance | %{ $_.Instances} | %{ $_.Tag}
  $name = ($tags | where {$_.Key -eq 'Name'} | %{$_.Value}) -join ','
  $costCenter = ($tags | where {$_.Key -eq 'CostCenter'} | %{$_.Value}) -join ','

  $tag = New-Object Amazon.EC2.Model.Tag
  $tag.Key = "CostCenter"
  $tag.Value = $costCenter
  New-EC2Tag -Resource $vol.VolumeId -Tag $tag
  Write-Host "Volume: " $vol.VolumeId " Cost Center Set To: " $costCenter
}

You will need the AWS Tools for Windows Powershell installed.

RabbitOperations Project Launched

An early preview release of my new open source project, RabbitOperations, is now available at https://github.com/SouthsideSoftware/RabbitOperations. The idea is to provide some tools for managing real-world applications that use RabbitMQ. It will support popular message buses like NServiceBus and Rebus with error replay, audit & error logging, sophisticated search capabilities and likely an integration with NewRelic to log stats about queue lengths etc. This very early release lacks a UI and is only suitable for experimentation and potential contributors.

Troubleshooting Assembly Binding Issues in .NET

I’ve been using fuslogvw.exe to troubleshoot assembly binding issues for several years so I was pretty surprised to find out that most of the guys on my team had not heard about it. Here’s a link to a great blog post that explains how to use it for those not in the know: http://www.meadow.se/wordpress/viewing-assembly-binding-logs-using-fuslogvw-exe/

Using Gulp with ASP.NET vNext and Visual Studio 2015 Preview

After playing with ASP.NET vNext and VS.NET 2015 a bit, I decided I wanted to switch from Grunt to my preferred build system for Node, Gulp. Although Gulp is supported, documentation is currently lacking and the VS.NET preview has some instability so it took me a few minutes to figure it out. Here are the steps that worked for me:

1) Make the package.json created by VS.NET complete so that npm will be able to add references.

npm init

2) Install gulp and uninstall grunt from the project

npm install -g gulp
npm install --save-dev gulp
npm uninstall --save-dev grunt

3) Install gulp-bower

npm install --save-dev gulp-bower

4) Add a gulpfile.js to the root of your web project with the following contents:

var gulp = require('gulp');
var bower = require('gulp-bower');

gulp.task('bower', function () {
    return bower({ layout: "byComponent"})
        .pipe(gulp.dest('wwwroot/lib'));
});

5) Modify project.json to use your new gulp task instead of grunt in the scripts section.

"scripts": {
        "postrestore": [ "npm install" ],
        "prepare": [ "gulp bower" ]
    }

6) Delete gruntfile.js

7) Close VS.NET and reopen and it should all work with gulp.

ASP.NET MVC Attribute Supporting SSL Terminated at Amazon Elastic Load Balancer

In my last post, I described an ASP.NET Web Api RequireHttps attribute that supports SSL terminated at a load balancer like Amazon’s ELB.  Here’s a RequireHttps attribute for ASP.NET MVC with load balancer support:

using System;
using System.Configuration;
using System.Web.Mvc;
using System.Web;
using System.Collections.Generic;

namespace MvcHelpers
{
    public class RequireHttpsSupportsLBAttibute : RequireHttpsAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsSecureConnectionConsideringLoadBalancer()) return;

            base.OnAuthorization(filterContext);
        }
    }

    public static class HttpRequestBaseHelper
    {
        public static bool IsSecureConnectionConsideringLoadBalancer(this HttpRequestBase request)
        {
            return request.IsSecureConnection || LoadBalancerSecured(request);
        }

        public static bool LoadBalancerSecured(HttpRequestBase request)
        {
            if (string.Equals(request.Headers["X-Forwarded-Proto"],
                "https"
                StringComparison.InvariantCultureIgnoreCase))
            {
                return true;
            }

            return false;
        }
    }
}

ASP.NET Web API 2 RequireSsl Attribute With Support For Terminating SSL At Load Balancer

Most modern load balancers, including Amazon’s Elastic Load Balancer (ELB), allow you to configure them to handle SSL. Although they can forward the request to your web nodes using SSL, it is more efficient to offload the SSL processing to the load balancer and forward requests from there to your web servers using plain HTTP on port 80. Load balancers that support offloading SSL generally inject a “X-Forwarded-Proto” header into the request with the value “http” or “https” to indicate the protocol of the original request. This approach is quite secure as the load balancer typically replaces any “X-Forwarded-Proto” header present in the original request. This is true for ELB.

You can use this header in ASP.NET Web API to make sure a request is secure. For example, here’s an attribute you can put on any controller or controller method to require SSL. It supports SSL terminated at the load balancer as well as plain old SSL straight to the server:

using System;
using System.Configuration;
using System.Linq;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

namespace AspNetApiHelpers
{
    public class RequireHttpsAttribute : AuthorizationFilterAttribute
    {
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps && !IsForwardedSsl(actionContext))
            {
                actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
                {
                    ReasonPhrase = "HTTPS Required"
                };
            }
            else
            {
                base.OnAuthorization(actionContext);
            }
        }

        private static bool IsForwardedSsl(HttpActionContext actionContext)
        {
            var xForwardedProto = actionContext.Request.Headers.FirstOrDefault(x => x.Key == "X-Forwarded-Proto");
            var forwardedSsl = xForwardedProto.Value != null &&
                xForwardedProto.Value.Any(x => string.Equals(x, "https", StringComparison.InvariantCultureIgnoreCase));
            return forwardedSsl;
        }
    }
}

Node.js Library for Delcom Visual Indicator Published

I just published my first npm package, delcom-indicator.  It’s a basic driver for the Delcom Visual Indicator.  I built it to support the node.js build light project I am currently putting together for the Raspberry Pi.  This library supports any platform that supports node-hid, which should include Windows, Mac and most Linux distributions.  It has been tested on Mac OS/X 10.9.2 and Raspian.

The publication process for node packages is a little easier than the one for .NET Nuget packages.  To get started, you need to setup an account at npm and authorize it on your computer:

npm adduser

Assuming you have a node.js project that includes packages.json in your directory, publishing is as simple as:

npm publish

Configuring a Raspberry Pi to Talk to Delcom USB With Node.js

Took a little digging, but I have Node.js 0.10.24 and Node-Hid successfully installed and talking to my Delcom USB indicator.  I wanted to take a minute to document the steps I took.  Before following the steps in this article, make sure you have your Raspberry Pi hooked up to the network.

Getting the OS Ready

Start by updating all your packages:

sudo apt-get update
sudo apt-get dist-upgrade

You will need a couple of additional packages required by node-hid, a node library used to communicate with USB HID devices like the Delcom USB Indicator:

sudo apt-get install libudev-dev libusb-1.0-0-dev

Node.js Install

As least as I write this you cannot get Node.js 0.10.x using apt-get. Instead, you have to install it yourself. Here’s the steps I used for node 0.10.24:

sudo mkdir /opt/node
wget http://nodejs.org/dist/v0.10.24/node-v0.10.24-linux-arm-pi.tar.gz
tar xvzf node-v0.10.24-linux-arm-pi.tar.gz
sudo cp -r node-v0.10.24-linux-arm-pi/* /opt/node

You’ll also have to put node into your path and set NODE_JS_HOME by editing your profile. Open up the profile:

sudo nano /etc/profile

Put the following right before you see “export PATH”:

NODE_JS_HOME="/opt/node"
PATH="$PATH:$NODE_JS_HOME/bin"

Once you reboot, you can verify the node installation by issuing the following command:

node -v

It should print out v0.10.24 on your console.

Node-Hid and Test Project

Now it’s time to create a little node project to test things out. This example will set things up in a directory called ~/nodetest:

mkdir ~/nodetest
cd ~/nodetest
npm install node-hid

You can then use nano to create a js file to execute with node:

nano test.js

Here’s the code:

var hid = require('node-hid');

var devices = hid.devices();

console.log('Devices:')
console.log(devices);

Once you plug in the Delcom device, you can run the app to find it as follows:

node test.js

You should see output like this:

[ { vendorId: 4037,
    productId: 45184,
    path: '0001:0005:00',
    release: 32,
    interface: 0 } ]

If you have multiple USB HID devices attached, they will appear in the list as well. The one with the vendorId given above is the Delcom device.

One More Thing

I prefer to write code on my Mac using Webstorm.  I get access to my Raspberry Pi console using ssh and transfer files with help from the netatalk AFP client installed as follows:

sudo apt-get install netatalk

Rolled Up My Sleeves and Got Raspberry Pi Booting

So it appears that my mistake was paying a little extra for the kit.  I reformatted the SD card, downloaded the new out of the box software (NOOBS), copied it onto the SD card, powered up the Pi and about 30 minutes later it was booting just fine into Raspbian Linux.  I’ve got to pick up a supported USB WiFi device today so I can get it onto the network.  I can then start testing some code.  Fun!

My First Bite of Raspberry Pi Not So Tasty

Got home late last night, ate dinner and sat down to boot up my new Raspberry Pi. I bought it as part of a kit that included a power supply, a case and an 8GB SD card with Raspberry Pi New Out of Box Software (NOOBS) installed. Plugged it in and booted to a kernel panic that indicates a problem with the boot device. Not exactly unexpected, but certainly disappointing. Tonight I’ll reformat the card and burn the NOOBS image onto it so I can try again.  Wish me luck!