Installing Ruby 2.0.0 with Dtrace Support

The aim of this post is to guide the reader through the process of installing ruby 2.0.0 into rbenv with dtrace probes enabled. As rbenv uses ruby-build, which currently downloads and compiles a copy of openssl rather than using the one homebrew i prefer to use the homebrew one.

Note that you MUST install xcode before installing anything, then install homebrew, rbenv, and lastly openssl.

ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"
brew install rbenv
brew install openssl

Next to overcome the fact that OSX doesn’t have an openssl ca certificate bundle, use the following brew to create and maintain one using the CA certs stored in your keychain.

brew tap raggi/ale && brew install openssl-osx-ca

Make a temporary directory to build the sources in, download the 2.0.0-p0 and extract it into this location, then navigate into the ruby-2.0.0-p0 directory containing the sources.

mkdir ~/temp && cd ~/temp
curl -L ftp://ftp.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p0.tar.bz2 | tar xjf -
cd ruby-2.0.0-p0

Run configure file with the arguments as listed below.

./configure --prefix=$HOME/.rbenv/versions/2.0.0-p0 --enable-dtrace \
--with-opt-dir=`brew --prefix openssl`

Within this rather verbose output you should see the following, this indicates that dtrace has been included.

checking whether dtrace USDT is available... yes

Build ruby, note I am invoking make with the ‘-j’ or ‘–jobs’ option tells make to execute many recipes simultaneously, in my case I chose 9 as I have eight cores (n of cores + 1).

make -j9

Now install ruby into rbenv with the label 2.0.0-p0.

make install

To try it out we will alter our shell to use the 2.0.0-p0 version.

rbenv shell 2.0.0-p0

Running ruby -v should output the following.

ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-darwin12.2.0]

You can remove the temporary directory you built ruby in now.

rm -r ~/temp

NOTE: Bundler has just been updated to cater for ruby 2.0.0 but you will need to retrieve the gem manually and install it as follows.

wget https://rubygems.org/downloads/bundler-1.3.0.gem
gem install bundler-1.3.0.gem
rm bundler-1.3.0.gem

Raspberry Pi Temperature and Humidity Project Construction

For some time I have had a Raspberry Pi languishing on my desk, like many I bought one early on and played around with it for a while and then got busy with other stuff. Recently however I have been looking into distributed sensor networks which led me to consider how I could use the Raspberry Pi to aid in my research. If I could get a number of these devices connected up together gathering some measurements of some sort, I could a) make some graphs, b) produce some useful test data and c) get some real world experience with sensor networks.

So I did a bit of research on what hardware I could connect up to the Raspberry Pi with the least amount of circuitry this led me to the AdaFruit site and in particular this article DHT Humidity Sensing on Raspberry Pi with GDocs Logging. This was as almost what I was after but still had a little to much “construction”. After searching around I managed to deduce that a small pre-made Arduino compatible board existed with all the circuitry already assembled, all that remained was to solder 3 wires onto the board and get this connected to the Raspberry Pi. After some foraging around in my computer “junk” I found some old case wiring which had small 4 pin connectors which could be plugged into the gpio header and could have their pins rejigged into any combination of one, two or 4 pin headers for maximum flexibility.

So to build this project you will need the following items, I have included the approximate cost.

Total cost $74.

Assembly is quite simple.

Solder three wires into the freetronics board, in my case I had red which i soldered into the data pin, white which I soldered into the 3.3v pin and black which I soldered into the ground pin.

Sensor Connection

Move the ground wire into it’s own 4 pin connector, and put the 3.3v and data pins at either end of another 4 port connector.

Four pin Connectors

Connect these as illustrated to the Raspberry Pi, being sure to triple check the location.

Connected to the Raspberry Pi

Bask in the glow of the little LED on the addon board which indicates you have powered it up.

Finished project connected to the network

First you will need to grab and install the bcm2835 library before building it. I grabbed the latest sources for Mike McCauley’s bcm2835 library and installed them on the pi.

pi@raspberrypi ~ $ wget http://www.open.com.au/mikem/bcm2835/bcm2835-1.14.tar.gz
pi@raspberrypi ~ $ tar xvzf bcm2835-1.14.tar.gz
pi@raspberrypi ~ $ cd bcm2835-1.14
pi@raspberrypi ~/bcm2835-1.14 $ ./configure
pi@raspberrypi ~/bcm2835-1.14 $ make
...
pi@raspberrypi ~/bcm2835-1.14 $ sudo make install

Download the software as instructed in the linked ADAFruit article, you will need git so install that first.

pi@raspberrypi ~ $ apt-get install git
pi@raspberrypi ~ $ git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code.git
pi@raspberrypi ~ $ cd Adafruit-Raspberry-Pi-Python-Code/
pi@raspberrypi ~/Adafruit-Raspberry-Pi-Python-Code $ cd Adafruit_DHT_Driver

Build the software.

pi@raspberrypi ~/Adafruit-Raspberry-Pi-Python-Code/Adafruit_DHT_Driver $ make

Run the Adafruit_DHT command.

pi@raspberrypi ~/Adafruit-Raspberry-Pi-Python-Code/Adafruit_DHT_Driver $ sudo ./Adafruit_DHT 2302 4
Adafruit_DHT 2302 4
Using pin #4
Data (40): 0x2 0x3e 0x0 0xde 0x1e
Temp =  22.2 *C, Hum = 57.4 %

I am working on another post with some details of how I am using this device, and the software I will be driving it with, this should go out in the next couple of weeks.

Hope others find this useful.

Update

2013-02-28 Removed the change to small change to the make file as it is not required anymore.

What is HMAC Authentication and why is it useful?

To start with a little background, then I will outline the options for authentication of HTTP based server APIs with a focus on HMAC and lastly I will provide some tips for developers building and using HMAC based authentication.

Recently I have been doing quite a bit of research and hacking in and around server APIs. Authentication for these type APIs really depends on the type of service, and falls into a couple of general categories:

  • Consumer or personal applications, these typically use a simple username and password, OAuth is used in some cases however this is more for identity of an individuals authorisation session within a trusted third party.
  • Infrastructure applications, these typically use a set of credentials which are different to the owners/admins credentials and provide some sort of automation API for business or devices to enhance the function or control something.

For infrastructure APIs I have had a look at a few options, these are explained in some detail below.

Basic Authentication

This is the simplest to implement and for some implementations can work well, however it requires transport level encryption as the user name and password are presented with ever request. For more information on this see Wikipedia Article.

Digest Authentication

This is actually quite a bit closer to HMAC than basic, it uses md5 to hash the authentication attributes in a way which makes it much more difficult to intercept and compromise the username and password attributes. Note I recommend reading over the Wikipedia page on the subject, in short it is more than secure than basic auth, however it is entirely dependent on how many of the safeguards are implemented in the client software and the complexity of the password is a factor.

Note unlike basic authentication, this does not require an SSL connection, that said make sure you read the Wikipedia article as there are some issues with man in the middle attacks.

HMAC Authentication

Hash-based message authentication code (HMAC) is a mechanism for calculating a message authentication code involving a hash function in combination with a secret key. This can be used to verify the integrity and authenticity of a a message.

Unlike the previous authentication methods there isn’t, as far as I can tell a standard way to do this within HTTP, that said as this is the main authentication method used by Amazon Web Services it is very well understood, and there are a number of libraries which implement it. To use this form of authentication you utilise a key identifier and a secret key, with both of these typically generated in an admin interface (more details below).

It is very important to note that one of the BIG difference with this type of authentication is it signs the entire request, if the content-md5 is included, this basically guarantees the authenticity of the action. If a party in the middle fiddles with the API call either for malicious reasons, or bug in a intermediary proxy that drops some important headers,the signature will not match.

The use HMAC authentication a digest is computed using a composite of the URI, request timestamp and some other headers (dependeing on the implementation) using the supplied secret key. The key identifier along with the digest, which is encoded using Base64 is combined and added to the authorisation header.

The following example is from Amazon S3 documentation.

"Authorization: AWS " + AWSAccessKeyId + ":"  + base64(hmac-sha1(VERB + "\n"
                   + CONTENT-MD5 + "\n"
                   + CONTENT-TYPE + "\n"
                   + DATE + "\n"
                   + CanonicalizedAmzHeaders + "\n"
                   + CanonicalizedResource))

Which results in a HTTP request, with headers which looks like this.

PUT /quotes/nelson HTTP/1.0
Authorization: AWS 44CF9590006BF252F707:jZNOcbfWmD/A/f3hSvVzXZjM2HU=
Content-Md5: c8fdb181845a4ca6b8fec737b3581d76
Content-Type: text/html
Date: Thu, 17 Nov 2005 18:49:58 GMT
X-Amz-Meta-Author: foo@bar.com
X-Amz-Magic: abracadabra

Note the AWS after the colon is sometimes known as the service label, most services I have seen follow the convention of changing this to an abbreviation of their name or just HMAC.

If we examine the Amazon implementation closely a few advantages become obvious, over normal user names and passwords:

  1. As mentioned HMAC authentication guarantees the authenticity of the request by signing the headers, this is especially the case if content-md5 is signed and checked by the server AND the client.
  2. An admin can generate any number of key pairs and utilise them independent of their Amazon credentials.
  3. As noted before these are computed values and can be optimised to be as large as necessary, Amazon is using 40 character secrets for SHA-1, depending on the hash algorithm used.
  4. This form of authentication can be used without the need for SSL as the secret is never actually transmitted, just the MAC.
  5. As the key pairs are independent of admin credentials they can be deleted or disabled when systems are compromised therefor disabling their use.

As far as disadvantages, there are indeed some:

  1. Not a lot of consistency in the implementations outside of the ones which interface with Amazon.
  2. Server side implementations are few in number, and also very inconsistent.
  3. If you do decide to build your own be advised Cryptographic APIs like OpenSSL can be hard to those who haven’t used them directly before, a single character difference will result in a completely different value.
  4. In cases where all headers within a request are signed you need to be VERY careful at the server or client side to avoid headers being injected or modified by your libraries (more details below).

As I am currently developing, and indeed rewriting some of my existing implementations I thought I would put together a list of tips for library authors.

  1. When writing the API ensure you check your request on the wire to ensure nothing has been changed or “tweaked” by the HTTP library you’re using, mine added a character encoding attribute to the Content-Type.
  2. Test that order of your headers is correct on dispatch of the request as well, libraries my use an hash map (natural ordered), this may break your signature depending on the implementation. In the case of Amazon they require you to sort your “extra” headers alphabetically and lower case the header names before computing the signature.
  3. Be careful of crazy Ruby libraries that snake case your header names (yes this is bad form) before presenting them to your code as the list of header names.
  4. When debugging print the canonical string used to generate the signature, preferably using something like ruby inspect which shows ALL characters. This will help both debugging while developing, and to compare against what the server side actually relieves.
  5. Observe how various client or server APIs introduce or indeed remove headers.

From a security stand point a couple of basic recommendations.

  1. Use content MD5 at both ends of the conversation.
  2. Sign all headers which could influence the result of the operation as a minimum.
  3. Record the headers of every API call that may have side affects, on most web servers this can be enabled and added to the web logs (again ideally this would be encoded like what ruby inspect does).

So in closing I certainly recommend using HMAC authentication, but be prepared to learn a lot about how HTTP works and a little Cryptography, this in my view cant hurt either way if you’re building server side APIs.

Update

Based on some of the comments made when I submitted this to hacker news I have compiled some extra links and observations.

One interesting point made was the issue of replay attacks, which is where a valid message is maliciously or fraudulently repeated or delayed. This is either performed by the originator or by a man in the middle who retransmits the message, possibly as a part of a denial of service.

nonce

To protect from these types of attacks a Cryptographic nonce, which is an arbitrary number usable only once in a message exchange between a client and a server. These are in fact optionally used within Digest authentication mentioned previously.

One of the comments linked an article which suggested use of nonce with HMAC as described in RFC 5849 The OAuth 1.0 Protocol. In this specification an nonce is paired a timestamp and included with each message, the timestamp can be used to avoid the need to retain an infinite number of nonce values for future checks, the server can reject messages with timestamps older than window of time nonce values are retained.

Based on the original post I have developed a flexible hmac authentication library called Ofuda for nodejs, this currently contains a small routine to hmac sign a list of headers for a given request. In the near future I plan to add validation of a signature and an implementation of nonce based on the aforementioned strategy.

How I use chef-solo with ubuntu 12.04

Having recently started working with chef I have come up with a simple method of kickstarting use of it in the small end of town. This really is designed for those of use managing a large number of very similar servers, or a small number of simple servers.

After watching this great presentation on chef by @benr from joyent, I decided it was time to roll up my sleeves and get started with chef. To do this I took some of his advice and my meager Unix knowledge and crafted a simple bootstrap method for my development Ubuntu systems, which I will describe in this post.

Firstly I get myself an ubuntu development system which I use to build my develop the profile I will use for this system in the future. If this is done locally I grab the ubuntu install CD for the server version and follow the default installation options with the only service I install being openssh. If your using a VPS this is typically what you get out of the box.

Because I am doing this on a local server I normally use ssh-copy-id to copy over my ssh public key the easy mode way.

ssh-copy-id admin@ubuntuserver

Next I run my bootstrap script to install my environment on the server, note the link below is retrieving a specific revision based on the raw link in the gist this may change based on my updates.

ssh admin@ubuntuserver -t -C 'curl https://raw.github.com/gist/3328844/2f4d74d49f8f7a2cd0b7a83a23fafe75d21241cf/gistfile1.sh | sudo bash'

In the next few steps I export my chef-solo template project to the system and build up a recipe for producing this type of system. You may do this differently, I have a script with all these commands in it but I have exploded it for this example.

I start my dev cycle by generating a new ssh key pair and upload that to github or bitbucket depending which one you use.

ssh admin@ubuntuserver -t -C "ssh-keygen -t rsa -b 4096 && cat ~/.ssh/id_rsa.pub"

Make the chef directory and chown it for my admin user.

ssh admin@ubuntuserver -t -C "sudo su - -c '(mkdir /var/chef && chown admin:admin /var/chef)'"

Clone my git project whilst retaining ownership of the files by my admin user, for those new to git see the awesome git book.

ssh admin@ubuntuserver -t -C "git clone git@github.com:wolfeidau/chef-solo-base.git /var/chef"

Initialise the sub-modules and update them, this is something I always forget unless I have a script to follow..

ssh admin@ubuntuserver -t -C "cd /var/chef && git submodule init && git submodule update"

Now you can run chef-solo just to ensure it is all running as expected.

ssh admin@ubuntuserver -t -C 'sudo chef-solo -c /var/chef/solo.rb -j /var/chef/node.json'

This template is comprised of:

  • solo.rb - Glue code which loads various directories.
  • node.json - This is the dna for your system and will be available to your recipes as meta.
  • cookbooks - This directory holds the cookbooks. ** main - This cookbook is where my default recipe is located and all its associated templates. *** templates - This holds all my templates which I use to craft new or replacement configuration files. ** openssl - This is my first external cookbook, once I work out what I am doing I tend to externalise a few functions using other peoples cookbooks.

Using the handy tree command we can see the overall structure of the template.

markw@chefdev1204:/var/chef$ tree
.
├── cookbooks
│   ├── main
│   │   ├── recipes
│   │   │   └── default.rb
│   │   └── templates
│   │       └── default
│   │           ├── bambooxml.erb
│   │           ├── pg_hba_conf.erb
│   │           ├── screenrc.erb
│   │           ├── serverxml.erb
│   │           ├── tomcat7.erb
│   │           └── zshrc.erb
│   └── openssl
│       ├── CHANGELOG.md
│       ├── CONTRIBUTING
│       ├── libraries
│       │   └── secure_password.rb
│       ├── LICENSE
│       ├── metadata.rb
│       ├── README.md
│       └── recipes
│           └── default.rb
├── node.json
├── README.md
└── solo.rb

8 directories, 17 files

In my example I have commented out a whole section of example code which bootstraps my CI server using chef, this is gives me some starting points. Note that I am not an authority on either chef or ruby so my scrappy sysadmin code may make some people grimace but it is a starting point.

Once you’re ready to start hacking remove the remote repo and add your own.

git remote rm origin

Next some rules I try and live by when using chef:

  1. Keep it simple, if a recipe looks complicated or you don’t understand it don’t use it.
  2. Don’t use chef as an alternate package manager, make packages using fpm and install them.
  3. Please reread #1.

Most importantly get started with this tool you will never look back once you have a few systems built using it.

To add more recipes from opscode-cookbooks account simply navigate to the base of your project and run something like the following example.

git submodule add https://github.com/opscode-cookbooks/openssl.git cookbooks/openssl

Once I have completed my chef project I check it out on my workstation and use rsync to push it to a clean target host for testing.

Again I run ssh-copy-id to copy my ssh key.

ssh-copy-id admin@ubuntuserver

Bootstrap chef onto the server.

ssh admin@ubuntuserver -t -C 'curl https://raw.github.com/gist/3328844/2f4d74d49f8f7a2cd0b7a83a23fafe75d21241cf/gistfile1.sh | sudo bash'

Create my chef directory.

ssh admin@ubuntuserver -t -C "sudo su - -c '(mkdir /var/chef && chown admin:admin /var/chef)'"

Using rsync and a locally checked out repo copy the files to the remote machine.

rsync -axvr -e ssh my-chef-project/ admin@ubuntuserver:/var/chef/

Building Ruby Projects with Bundler and the Bamboo Ruby Plugin

The latest release of the Ruby plugin I develop for Atlassian Bamboo now includes some new configuration options for Bundler along with a number of other additions and improvements. In this post I want to focus on the new options available in the Bundler task, and illustrate how they are used to make Ruby builds simpler.

In the past with my plugin the administrator of the CI server had two options when managing the gems associated with a build:

  1. Install all the gems required by the project prior to performing a build
  2. Permit bundler to write to the local ruby installations gem directory

In my view neither of these options is ideal, so I decided I would do some research into staging gems within the working copy of a build. The aim here was to build a ruby project without tainting the local ruby installation, which is one of the key objectives of CI. After some reading I discovered that Bundler could help stage my gems, therefore saving me from doing so.

To take advantage of this feature in Bundler the user was required to pass a couple of switches to install command and then run Bundler’s exec command for all subsequent ruby executions.

To illustrate this using the Bamboo Ruby plugin I will run through configuring a build with a simple rails project.

Firstly we need a ruby, which I install using RVM, you could just use the system provided one if your on OSX.

$ rvm install 1.9.3

Then use this install.

$ rvm use 1.9.3

Now the only gem you need to install is bundler.

$ gem install bundler

Now within Bamboo install the Bamboo Ruby Plugin via the Universal Plugin Manager.

Ruby Plugin Installed

Now go to Server Capabilities in Administration section, and click the Detect Server Capabilities button, this should find your ruby installation as seen below.

Ruby Server Capabilities

Next setup a project and a release plan.

Create Plan

Then within your build Job add the Bundler Task, configuring the path option to vendor/bundle and ticking the binstubs option.

Bundle Task

Next add a Rake task to run your database migrations.

Rake DB Migrate Task

Next we want to run the tests in our project, in my case I am using RSpec2 so I use the spec rake task.

Rake Run RSpec Task

As I like to see my test outputs in the CI server I have enabled xml output with my RSpec configuration file and added the rspec_junit_formatter gem to my Gemfile. This produces a JUnit XML report file named rspec.xml which Bamboo parses into test results report.

JUnit Task

Now you should enable your build and run it, all going well you should have green, otherwise have a look at the build log and see what the issue was.

So that wraps up my demonstration of Bamboo Ruby Plugin using the awesome bundler gem to enable simple ruby build environments.