Stuff… And Things…

I do… stuff and build… things.

Building Emacs 24.4 From Source on the Mac

| Comments

Emacs 24.4 is officially released and Mac OS 10.10 Yosemite has arrived. As always, time to build.

Before begin you will need Xcode installed (free in the Mac App Store) to build Emacs. Of course if your the sort of person who uses Emacs, you’re probably the sort of person who has Xcode installed.

To build Emacs you also need Autoconf and Automake and Apple has stopped shipping these with Xcode. If you don’t already have them (hint: which autoconfig and which automake) you will need to install them.

Ban Bad Bots by IP

| Comments

In the Internet age we live in, it’s not uncommon for web servers to be hit with Unintentional, not so Distributed, Denial of Service (DoS) Attacks. The attacks itself is intentional, but it’s not trying to bring down the server. It’s just some stupid ‘bot running a probe as fast as it can and, as a side effect, bogging down your server.

Bots are evil, but at least smart bots rate limit themselves to keep off the radar.

The typical stupid bot is running a password probe against an admin login. If you run any WordPress sites, you see this. All. The. Time. There are many good options to prevent these attacks, including renaming well known URLs, IP filtering, and automatic IP banning software, like Fail2ban.

However, sometime you just need to make the attack go away now. For that, I have a couple of Bash functions/tcsh alias.

Laziness: SCP Alias

| Comments

I often find myself needing to download files to my local box via SCP. Which means entering the hostname, the path, and the filename in to my terminal window. However, I’m really lazy, if I can’t auto complete it or cut and paste it, I’m not happy. Enter this simple Bash function:

Laziness: Remote SSH Usernames

| Comments

I’m lazy and I’m always looking for ways to avoid any unneeded typing. Here’s a little OpenSSH configuration tip that can save you up to 16 characters (if you have crazy long usernames).

Magic IP Address Shortcuts

| Comments

TL;DR

In most cases, if you enter 0 for an IP address it will expand to 0.0.0.0. Likewise, 127.1 will expand to 127.0.0.1. Why? Magic.

Not Magic

But really, why do these shortcuts exist and how do they work? It can’t be as simple as adding zeros, if it was 127.1 would more logically expand to 127.1.0.0.

Turns out it’s a historic quirk in the inet_aton() function which is used, directly or indirectly, by most software to parse IP addresses in dotted-quad format into integers.

Cross-Domain AJAX Request in Development

| Comments

Sometimes an AJAX request on a page you’re developing needs to hit a server on a different domain. Web browsers’ Same-Origin Policy means (among other things) that other domains called from AJAX need to be whitelisted using the Access-Control-Allow-Origin header.

While this limits the damage malicious Javascript injected into a page can do, it’s annoying in development. You could whitelist your dev box, 0.0.0.0, or 127.0.0.1 (depending on how you work), but that’s ugly.

Fortunately, there’s an easier way, temporarily disable same-origin policy.

Luminate Online Server API Gem

| Comments

As part of the work Indra did for Stand Up To Cancer’s telethon, I need to make use of Convio/blackbaud’s Luminate Online Server APIs. Luminate Online is a widely used fundraising platform and relationship manager for non-profits.

I’ve turned that development work into open source in the form of gem providing Ruby bindings to the APIs.

I have only implemented a handful of endpoints, Luminate Online doesn’t have any kind of test mode or sandbox, any testing has to be done with live data. However, I’ve used a meta programming approach making it easy to quickly add additional endpoints.

All of the endpoints I have implemented have been used in anger.

The details are in the repo: https://github.com/spikex/luminate

It’s in the Logs, Stupid

| Comments

Yesterday, I was involved in a fire drill around the launch of a new Rails site on a very tight time frame. The site worked fine in development/staging, but the index was taking upwards of 10 seconds to render in production.

Because it worked outside of production we leapt to the conclusion it was related to the hosting infrastructure. We checked Apache, Passenger, server load, network configuration, and so on. Nothing.

Finally, I thought to check log/production.log, and there is was:

1
2
3
Processing by BlahController#index as */*
  Rendered blah/_carousel.html.erb (5795.2ms)
  Rendered blah/index.html.erb within layouts/site (5801.5ms)

We quickly tracked it down some image processing that wasn’t being cached. It didn’t show outside of production because the image assets were different. I won’t bore you with the details.

However, I will bore enlighten you as to my point. When debugging a problem, start with the simple things. The Rails logs aren’t very detailed, but they provide more than enough information to quickly drill down to problems in your code.

Building Ruby 1.8.7 on FreeBSD 10

| Comments

If you try to build Ruby 1.8.7 with RVM you will see:

1
2
3
4
5
# rvm install 1.8.7
[...]
./lib/fileutils.rb:1430: [BUG] unexpected local variable
ruby 1.8.7 (2012-02-08 patchlevel 375) [amd-freebsd10]
*** [./.rbconfig.time] Signal 6

This is because FreeBSD 10 ships with the Clang compiler instead of GCC and Ruby versions priory to 1.9.3-p194 do not support Clang.

The work-around, is to install GCC, either with pkg:

1
# pkg install gcc

or from Ports:

1
2
# cd /usr/ports/lang/gcc
# make install clean

Once you have gcc you can install 1.8.7 with:

1
# CC=/usr/local/bin/gcc47 rvm install 1.8.7

This should work with older versions of Ruby 1.9 as well.

What on earth would you want to install 1.8.7? Two words: Legacy Apps…

Dynamic Keys for Strongbox

| Comments

Previously, Strongbox, my gem for using Public Key Encryption with ActiveRecord, allowed only one key pair for encrypting all of the records for a given ActiveRecord model. I’ve had a number of requests to make it possible to dynamically choose the keys on a per record basic and version 0.6.0 adds this feature.

The values of :public_key, :private_key, and :key_pair can be in one of the following formats:

A string containing path to a file. This is the default interpretation of a string.

1
2
encrypt_with_public_key :secret,
   :key_pair => File.join(RAILS_ROOT,'config','keypair.pem')

A string contanting a key in PEM format, needs to match this the regex /^-+BEGIN .* KEY-+$/

1
2
3
encrypt_with_public_key :secret,
  :key_pair =>
    "-----BEGIN RSA PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,BFE700E4DDA4C434\n\nDfZD7FKM4zLJdb[...]"

A symbol naming a method to call. Can return any of the other valid key formats.

1
2
3
encrypt_with_public_key :secret,
  :public_key => :public_key_method,
  :private_key => :private_key_attribute

An instance of OpenSSL::PKey::RSA. Must be unlocked to be used as the private key.

1
2
3
4
KEY_PAIR = OpenSSL::PKey::RSA.new(key,password)
# [...]
encrypt_with_public_key :secret,
   :key_pair => KEY_PAIR

Using this, you can automatically create per record public keys:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
require 'openssl'

# Assumes the migration contains:
#  t.string :description
#  t.binary :secret
# that you are collecting a password to encrypt the private key,
# and that the secret is small

class User < ActiveRecord::Base
  attr_accessor :password
  encrypt_with_public_key :secret,
    :key_pair => :key_pair

  def after_initialize
     rsa_key = OpenSSL::PKey::RSA.new(2048)
     cipher =  OpenSSL::Cipher::Cipher.new('des3')
     key_pair = rsa_key.to_pem(cipher,self.password) + rsa_key.public_key.to_pem
  end
end

Important Caveat - Currently, Strongbox encrypts the attribute as soon as it’s assigned (this will change in version 1.0). The means that the public key must be available before the attribute is assigned, hence the use of after_initialize to generate the key pair. Even so, this will fail if you do something like:

1
user = User.new(params[:user])

because the attributes are set before after_initialize is called.

Instead, use something like:

1
2
3
user = User.new
user.password = params[:password]
user.attributes = params[:user]

Version 1.0 will allow you to control when the encryption occurs, making this less of an issue.