Thursday, January 30, 2014

vmconnect

I wrote a script called _vmconnect that either simply logs into a VirtualBox guest, or starts it headlessly first and then logs in.  With _vmconnect set as the command for an iTerm2 profile, I can open the session without caring whether the machine is running or not.

The full script became a bit unwieldy for a blog post (and I didn't want to maintain it forever within Blogger), so I published it to github.  You'll find it in my bin repository: https://github.com/sapphirecat/bin

Enjoy!

Update: _vmconnect version 1.0.3 fixes a possible data loss: if the VM was booted by _vmconnect, terminating the ssh connection it logged in with would also abort the VM.  You SHOULD pull if you are using _vmconnect 1.0.2 or prior (check your _vmconnect --version output!)

Friday, January 17, 2014

Brief notes on Packer

packer.io says they build identical images for multiple platforms such as EC2, VirtualBox, VMWare, and others (with even more on the way via plugins).  However, it's more about customizing a machine already running than it is about fabricating a new machine out of whole cloth and distributing the result to disparate services.  That is, the AMI builder starts from another AMI; the VirtualBox builder starts from an installer ISO (with commands to make the install unattended) or an OVF/OVA export and customizes that to produce an output OVF/OVA export.  This is, as I understand it, in contrast to Vagrant or Docker images, which build one image that runs on many systems.

Packer is about customizing existing machines that already exist in some form, then building the result as a new image for the same system.  If you're really interested in taking "one base image" to many environments, then Docker is probably the better choice there.  It's built on Linux Containers, where the virtualization happens inside the host kernel instead of a dedicated hypervisor, which makes it possible to run a bit-for-bit identical container both  inside EC2 (even PV) and inside VirtualBox.

In another contrast to vagrant, packer supports a shell provisioner that lets you upload a shell script and run wild.  Last I knew, which is probably woefully out of date, vagrant supported puppet by default and chef-solo as an option.  Since I happen to have an existing build system constructed around shell scripts for provisioning (with a dash of perl or php for the trickier parts), albeit specifically for EC2 instances, packer might suit my codebase and philosophy a little better.

Put another way, and beating the dead horse a bit more, Vagrant and Docker are about creating One True Image and later instantiating that single image on different underlying services (including EC2 and VirtualBox).  Packer is about coordinating the construction of native images for those services; it's about making predictable, repeatable changes to a running instance in the service and exporting the result for later use.

Unrelated to the above, packer is written in go 1.2 and distributes binaries for various platforms.  Docker is also written in go (but I'm not sure of the version target), leaving Vagrant in Ruby as the odd man out.  Having been subjected to rvm to install octopress at one point, I'm much more amenable to smaller dependency footprints... like static binaries produced by Go.  (Then again, I heard later that everyone hates rvm.)

Update 14 Feb 2014: I thought of one more useful contrast among the projects.  Docker and Packer are aimed toward building immutable, self-contained images.  Vagrant is focused on setting up (repeatable) development environments--particularly, in how it includes only the VirtualBox provider by default, and uses shared folders to persist changes as you develop.

Monday, January 13, 2014

Event Handler Optimization

I've been coding with jQuery for a long time.  I'm pretty sure 1.3 was new when I started.

One of the things that had always been "good enough" for me was to attach event handlers en masse directly to the elements involved: $('a.history').click(popupHistory);

It so happens that if the page is a table of 50 customers in the search result, each with a history link, then 50 handlers get bound.  jQuery takes care of all the magic, but it can't really optimize your intent.  Newer versions of jQuery—that is, 1.7 and up—support a more intelligent event-binding syntax which is a beautiful combination of two things:
  1. A single handler on an element containing all of the interesting ones, invoked as the event bubbles.
  2. A selector for the handler to filter interesting children.  The handler is only called if the event occurs within a child matching that selector.
These features are part of .on().  For an idea how this works:

<div id="box"></div>
<script type="text/javascript">
$('#box').on('click', 'a.history', function (e) {
popupHistory($(e.target).closest('[data-customer]').attr('data-customer'));
});
// populate the #box with HTML somehow, e.g.:
$('#box').html('<div data-customer="3">Customer! <a class="history" href="#">View Order History</a></div>');
</script>

Not only does this attach one event handler under the hood, but that event handler will be run for any present or future children.  The parent must be there for .on() to bind the handler to (otherwise, you'd have an empty jQuery set, and nothing would happen), but children will be detected by that handler when the event fires.

In the presence of dynamically added/removed elements, then, it's a double optimization: not only does only one handler get bound in the first place, but the handlers don't have to be changed on a per-element basis when children are added or removed.

Thursday, January 9, 2014

Smart Clients and Dumb Pipes for Web Apps

After something like 8 years of coding for the web, both in new and legacy projects, across four companies and some personal projects, I've come to a philosophy on web application layout:
If you require that the client has JavaScript, then you may as well embrace the intelligence of your client-side code.  Let your AJAX calls return simple messages, to be converted to a visible result for the user by code that shipped alongside that UI.

Wednesday, November 13, 2013

The Image's Revenge

Long ago, some programming languages supported image files, which were the running code and data, placed in a file for reloading later.  Wikipedia is vague on the details, but I believe the major benefit was load speed—an image could restore already-compiled code from a single, more-linear file instead of needing to read and evaluate the sources again.

In modern DevOps, we use images all the time.  We even call them images.  The only difference is that these images are built at the level of the filesystem and designed for an external OS/hypervisor to run.  Or if you're willing to give up some of the "can run anything" capability, they can be built without the filesystem.  Just your app and a hypervisor.

Friday, October 18, 2013

TLS Cipher Suites in 2013

    Things I learned digging around the RFCs and testing with the ssllabs server test:
    1. SSLv3/TLSv1 ciphers listed in the original specifications with forward secrecy are all DES (very weak) or 3DES (less weak).
    2. AES ciphers for TLSv1 were originally specified in RFC 3268 in 2002, and did not make it into XP's SChannel implementation.  I believe this is why they aren't present in IE8/XP.  If the link is trustworthy, the only ciphers available on IE/XP are RC4 and 3DES, neither of which can be considered excellent choices today.
    3. IE/XP does not truly offer forward secrecy because it doesn't support RSA modes with DHE, only DSS which has a 1024-bit limit; much of the TLS infrastructure has moved to require 2048-bit keys recently as 1024 is no longer considered adequate.
    4. TLS specifications require one mandatory cipher, presumably to ensure minimum interoperability.  In TLSv1.2 (RFC 5246, published in 2008), that cipher is AES128-SHA.  Earlier versions including TLSv1 and TLSv1.1 listed 3DES-SHA.
    5. Camellia cipher suites were defined in RFC 4132 in 2005.  That RFC has been superseded by RFC 5932 in 2010; the latter uses the SHA-2 hash family instead of SHA-1.
    6. Camellia itself is expected to be of similar security to AES; current attacks on AES are better, but it's likely that AES is more widely studied.
    7. SHA-2 hash family MACs were introduced in TLS v1.2.  It is believed that the older MD5/SHA-1 functions are still secure as used in TLS.  To the best of my knowledge, SHA-2 suites are only available when using TLSv1.2.
    8. ECDHE suites are defined RFC 4492, from 2006; including a ClientHello extension to indicate support.
    9. ECDHE is not required (though it is listed) in TLSv1.2, nor is usage of TLSv1.2 a requirement for using ECDHE.  Recent versions of Firefox support ECDHE suites in conjunction with TLSv1.  Older versions—Firefox 21/Fedora 19 for instance—do not.
    10. Some browsers prefer alleged key length over other considerations, and prioritize 3DES with its "168" bit key over AES128.  It's actually designated by NIST as providing 80 bits of security, though it could be providing up to 112 bits.
    11. The default cipher policy provided by AWS Elastic Load Balancers enables only SSLv3/TLSv1 and an extremely limited set of ciphers: AES128 and 256, 3DES, and RC4, with no forward secrecy suites.  (Suites are configurable in the AWS Console, but not cipher preference order, nor some renegotiation options.  Renegotiation settings are implicit in the choice of supporting, or not, the more-recent TLS versions.)

      Saturday, October 5, 2013

      The Lavabit Problem: the Universal TLS Key

      Lavabit refused to hand over the key to the whole kingdom for the U.S. Government to ostensibly capture the traffic of one user.  The judge ruled in the prosecution's favor in the resulting court case:
      Judge Claude Hilton said that it was effectively Levison's fault that sites have only a single private SSL key.
      Ars doesn't evaluate the truth of that, but technically, it could be accurate.  The Perfect Forward Secrecy modes of TLS—DHE and ECDHE—effectively generate a key per connection, authenticating the parameters used to create it with the server's certificate (which is in turn authenticated by the CA system.)  However, if Lavabit's servers were set up to allow RSA-only modes, then that configuration introduces the weakness.  Under RSA, the server's private key becomes the master private key, capable of decrypting any connection traffic in those modes, because that private key is used to encrypt all the traffic.