<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[jeremykendall.net]]></title>
  <link href="https://jeremykendall.net/atom.xml" rel="self"/>
  <link href="https://jeremykendall.net/"/>
  <updated>2018-12-04T02:10:04-06:00</updated>
  <id>https://jeremykendall.net/</id>
  <author>
    <name><![CDATA[Jeremy Kendall]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Will Senior Engineer for Food]]></title>
    <link href="https://jeremykendall.net/2016/06/24/will-senior-engineer-for-food/"/>
    <updated>2016-06-24T13:32:28-05:00</updated>
    <id>https://jeremykendall.net/2016/06/24/will-senior-engineer-for-food</id>
    <content type="html"><![CDATA[<p><strong>UPDATE:</strong> Sorry companies that didn&rsquo;t snatch me up while I was available, but
I&rsquo;m no longer on the market! As of August 2016 I&rsquo;m working as a Senior Software
Engineer at <a href="https://alegion.com/">Alegion</a>. I&rsquo;m stoked to be a part of an
amazing company and a member of one of the best teams I&rsquo;ve ever had the
pleasure to work with.</p>

<p><img src="https://jeremykendall.net/images/i_got_the_job.gif"></p>

<hr />

<p>After two amazing, challenging, crazy, exhausting years with <a href="http://graphstory.com/">Graph Story</a>,
I&rsquo;ve decided that it&rsquo;s time to find a new challenge and a new workplace to call home.</p>

<p>I&rsquo;ve grown more as a developer in the past two years than I have in my entire
career. I&rsquo;ve also worked harder than I&rsquo;ve ever worked before. At the end of these past
two years I find myself utterly exhausted and in need of a change of pace.</p>

<h2>Available for Hire</h2>

<p><img src="https://c2.staticflickr.com/8/7456/27604645770_c22fdf7662_c.jpg"></p>

<p>If you&rsquo;re in search of a Senior Engineer to join your dev team, I&rsquo;m looking and
immediately available! I bring ~15 years of web development experience to the table, a
passion for testable, maintainable code, an insatiable appetite for learning
new things, and some leadership experience.</p>

<p>If you&rsquo;d like to know more, here&rsquo;s my <a href="https://github.com/jeremykendall/resume">resume</a>
(a printable version is <a href="https://gitprint.com/jeremykendall/resume">available here</a>),
you can take a look at my <a href="https://github.com/jeremykendall">open source work on GitHub</a>, or even
spend a few minutes browsing through <a href="https://www.flickr.com/photos/jeremykendall">some of my photos</a>.</p>

<h2>What I&rsquo;m Looking For</h2>

<p>I want to get out of my <a href="http://giphy.com/gifs/thecomebackhbo-comeback-the-val-cherish-3rgXBre36c9Bnz5hV6">comfort zone</a>
and learn and do some new things. Don&rsquo;t need a PHP dev but you&rsquo;re looking for a
great Senior Engineer? If you&rsquo;re willing to teach, I&rsquo;m willing to learn (with
the caveat that I&rsquo;d much prefer an open source shop).</p>

<p>I need to <a href="http://giphy.com/gifs/photo-70s-muppets-gEfrwXsPRk14Q">work remotely</a>. My wife and I are about to have kiddo #2 and both of
our families are here in Memphis. Relocating right now would be extremely
difficult, although I would consider relocating at some point in the near
future for the right opportunity.</p>

<p>Additionally, here are the top three things I&rsquo;m looking for in a new employer:</p>

<ol>
<li>Work-life balance: I&rsquo;m a crazy hard worker, and I can and will work some
really long hours, but I&rsquo;m looking for 40-50 hours/week as a regular thing.</li>
<li>A strong engineering culture working on big things: I&rsquo;m less concerned about what you do as a
company than I am with your engineering culture and practices. If you have a
medium-large group of brilliant engineers that walk the best-practices walk,
I&rsquo;m in.</li>
<li>Tech community support and involvement: I want to work for a company that
values sending engineers to conferences, supports and uses open source
software, gives back to the community by means of supporting user groups,
open sourcing tools where possible, and contributing to open source projects
as a matter of course.</li>
</ol>


<h2>Contact Info</h2>

<p>If you&rsquo;d like to <a href="http://english.stackexchange.com/questions/64733/why-do-we-talk-turkey">talk turkey</a>,
hit me up at jeremy -at- jeremykendall -dot- net. I look forward to hearing from you!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Detecting and Converting File Encoding]]></title>
    <link href="https://jeremykendall.net/2015/05/08/detecting-and-converting-file-encoding/"/>
    <updated>2015-05-08T09:03:01-05:00</updated>
    <id>https://jeremykendall.net/2015/05/08/detecting-and-converting-file-encoding</id>
    <content type="html"><![CDATA[<p>I had a couple of files show up in a project that weren&rsquo;t utf-8 encoded and
needed to be converted. In the past, I found detecting encoding and converting
from one encoding to another to be an arcane and challenging task. This morning
it only took a few tries on Google and, a few <a href="https://superuser.com">superuser.com</a>
answers later, I was good to go.</p>

<h2>Encoding Detection</h2>

<p>I was quickly able to determine that the CSV file in question was encoded with <code>utf-16le</code> by using the following command:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>$ file -I unknown-encoding.csv
</span><span class='line'>unknown-encoding.csv: text/plain; charset=utf-16le</span></code></pre></td></tr></table></div></figure>


<h2>Converting to UTF-8</h2>

<p>Converting the file to a new encoding was just as easy:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>iconv -f utf-16le -t utf-8 unknown-encoding.csv &gt; new-encoding.csv</span></code></pre></td></tr></table></div></figure>


<h2>References</h2>

<p>The commands above were sourced from the following superuser questions and accepted answers:</p>

<ul>
<li><a href="http://superuser.com/questions/151972/determining-the-encoding-of-a-file-on-mac-os-x">Determining the encoding of a file on Mac OS X?</a></li>
<li><a href="http://superuser.com/questions/151981/converting-the-encoding-of-a-text-file-mac-os-x">Converting the encoding of a text file (Mac OS X)</a></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Forcing an NTP Update]]></title>
    <link href="https://jeremykendall.net/2014/10/06/forcing-an-ntp-update/"/>
    <updated>2014-10-06T09:44:01-05:00</updated>
    <id>https://jeremykendall.net/2014/10/06/forcing-an-ntp-update</id>
    <content type="html"><![CDATA[<p><strong>UPDATE</strong>: Dan Horrigan <a href="https://twitter.com/dhrrgn/status/519166134537310208">pointed out a much better solution</a>
to this problem on Twitter, one that has nothing to do with NTP at all. He adds
a VirtualBox config option in his <code>Vagrantfile</code>s to update the virtual
machine&rsquo;s time from the host every 10 seconds. Nice!</p>

<div><script src='https://gist.github.com/9e31f6de41d83f21107a.js'></script>
<noscript><pre><code># ...

    config.vm.provider :virtualbox do |v|
        # ... Other stuff here
        
        # Set the timesync threshold to 10 seconds, instead of the default 20 minutes.
        v.customize [&quot;guestproperty&quot;, &quot;set&quot;, :id, &quot;/VirtualBox/GuestAdd/VBoxService/--timesync-set-threshold&quot;, 10000]
    end

# ...</code></pre></noscript></div>


<p><strong>UPDATE 2</strong>: Oops. I didn&rsquo;t explain that correctly. Here&rsquo;s Dan to set the matter straight:</p>

<blockquote class="twitter-tweet" lang="en"><p><a href="https://twitter.com/JeremyKendall">@JeremyKendall</a> that is slightly wrong. It sets the drift threshold, so it only syncs if it is 10 seconds or more off.</p>&mdash; Dan Horrigan (@dhrrgn) <a href="https://twitter.com/dhrrgn/status/519246842769727488">October 6, 2014</a></blockquote>


<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>


<p><strong>ORIGINAL POST</strong>: I frequently find myself needing to update the time on my Vagrant boxes.
This is especially true when I&rsquo;m testing <a href="https://github.com/jeremykendall/query-auth">Query Auth</a> between two different
Vagrant boxes (mimicking a client/server relationship) as Query Auth
will fail a request with a timestamp that varies too greatly from the server&rsquo;s
timestamp (+-15 seconds by default). Even though I run <a href="http://www.ntp.org/">NTP</a> on all my virtual
servers, time drift is a frequent problem. Furthermore, when the drift is too great
(can&rsquo;t find a reference to how large the drift needs to be), NTP won&rsquo;t correct
it all at once.</p>

<p>A quick Google search later and, once again, it was Stack Overflow the rescue,
courtesy of <a href="http://askubuntu.com/a/256004/41943">Martin Schröder&rsquo;s answer</a> to the question <a href="http://askubuntu.com/questions/254826/how-to-force-a-clock-update-using-ntp">&ldquo;How to force a clock update using ntp?&rdquo;</a></p>

<p>One quick bash script later and excessive clock drift is now a trivial issue.</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>#!/bin/bash
</span><span class='line'># Forces an ntp update
</span><span class='line'>#
</span><span class='line'># Based on SO user Martin Schröder's answer to "How to force a clock update
</span><span class='line'># using ntp?": http://askubuntu.com/a/256004/41943
</span><span class='line'>
</span><span class='line'># Fail fast (set -e will bail at first error)
</span><span class='line'>set -e
</span><span class='line'>
</span><span class='line'>if [ "$EUID" -ne 0 ]; then
</span><span class='line'>    echo "ERROR: '$0' must be as root."
</span><span class='line'>    exit 1
</span><span class='line'>fi
</span><span class='line'>
</span><span class='line'>service ntp stop
</span><span class='line'>
</span><span class='line'>echo "Running 'ntpd -gq'"
</span><span class='line'>ntpd -gq
</span><span class='line'>
</span><span class='line'>service ntp start</span></code></pre></td></tr></table></div></figure>


<h2>Postscript</h2>

<p>If you&rsquo;re unfamiliar with the particulars of creating bash scripts, here are the
steps you can take to create your own version of the above script. You may need
to preface the commands using <code>sudo</code>.</p>

<ul>
<li>Copy and paste the above script into a text file (I&rsquo;ve named mine <code>force-ntp-update</code>).</li>
<li>On the command line, call <code>chmod a+x /path/to/force-ntp-update</code> to allow all users to execute the command.

<ul>
<li>If you&rsquo;re the only user who should be able to execute the command, change the above to <code>chmod u+x /path/to/force-ntp-update</code>.</li>
</ul>
</li>
<li>Move the script somewhere in your path: <code>mv /path/to/force-ntp-update /usr/local/bin</code>.</li>
<li>Done!</li>
</ul>


<p>Now anytime you need to force an update, simply call <code>sudo force-ntp-update</code>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Ubuntu 14.04 Gearman Config Bug]]></title>
    <link href="https://jeremykendall.net/2014/09/04/ubuntu-14-dot-04-gearman-config-bug/"/>
    <updated>2014-09-04T07:48:10-05:00</updated>
    <id>https://jeremykendall.net/2014/09/04/ubuntu-14-dot-04-gearman-config-bug</id>
    <content type="html"><![CDATA[<p>While configuring <a href="http://gearman.org/">Gearman</a> (for async jobs here at Graph Story), I ran
across a bug that causes Gearman to ignore its config file. The bug shows up on
Ubuntu 14.04 Trusty Tahr in Gearman version 1.0.6-3 installed from the Ubuntu
repositories.</p>

<p>Full disclosure: I can only confirm the existence of this bug in the above
mentioned environment.  I have not tested for the bug in any other
configuration.</p>

<h2>Bug Report - TL;DR</h2>

<p>There is a <a href="https://bugs.launchpad.net/ubuntu/+source/gearmand/+bug/1260830">bug report</a> filed by Artyom Nosov which details the issue and
includes a patch.  The <a href="https://launchpadlibrarian.net/159679541/gearman-job-server.upstart.patch">patch diff</a> is linked from the <a href="https://bugs.launchpad.net/ubuntu/+source/gearmand/+bug/1260830">bug report</a> and
is included below:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='diff'><span class='line'><span class="gh">diff -urN gearmand-1.0.6-old/debian/gearman-job-server.upstart gearmand-1.0.6/debian/gearman-job-server.upstart</span>
</span><span class='line'><span class="gd">--- gearmand-1.0.6-old/debian/gearman-job-server.upstart2013-11-11 01:58:42.000000000 +0400</span>
</span><span class='line'><span class="gi">+++ gearmand-1.0.6/debian/gearman-job-server.upstart20132013-12-13 22:30:32.392281779 +0400</span>
</span><span class='line'><span class="gu">@@ -9,4 +9,7 @@</span>
</span><span class='line'>
</span><span class='line'>  respawn
</span><span class='line'>
</span><span class='line'>   -exec start-stop-daemon --start --chuid gearman --exec /usr/sbin/gearmand -- --log-file=/var/log/gearman-job-server/gearman.log
</span><span class='line'>   +script
</span><span class='line'>   +    . /etc/default/gearman-job-server
</span><span class='line'>   +    exec start-stop-daemon --start --chuid gearman --exec /usr/sbin/gearmand -- $PARAMS --log-file=/var/log/gearman-job-server/gearman.log
</span><span class='line'>   +end script
</span></code></pre></td></tr></table></div></figure>


<h2>The Fix</h2>

<p>Gearman runtime configuration is handled by <code>/etc/default/gearman-job-server</code>
in Ubuntu.  The default upstart job does not use the Gearman config file,
causing Gearman to run with its defaults, which may or may not be acceptable to
you. To resolve the issue, update <code>/etc/init/gearman-job-server.conf</code> using the
diff included above.  For reference, here is my entire
<code>gearman-job-server.conf</code> file:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='diff'><span class='line'># -*- upstart -*-
</span><span class='line'>
</span><span class='line'># Upstart configuration script for &quot;gearman-job-server&quot;.
</span><span class='line'>
</span><span class='line'>description &quot;gearman job control server&quot;
</span><span class='line'>
</span><span class='line'>start on (filesystem and net-device-up IFACE=lo)
</span><span class='line'>stop on runlevel [!2345]
</span><span class='line'>
</span><span class='line'>respawn
</span><span class='line'>
</span><span class='line'># exec start-stop-daemon --start --chuid gearman --exec /usr/sbin/gearmand -- --log-file=/var/log/gearman-job-server/gearman.log
</span><span class='line'>
</span><span class='line'># PATCH: https://bugs.launchpad.net/ubuntu/+source/gearmand/+bug/1260830
</span><span class='line'>script
</span><span class='line'>    . /etc/default/gearman-job-server
</span><span class='line'>    exec start-stop-daemon --start --chuid gearman --exec /usr/sbin/gearmand -- $PARAMS --log-file=/var/log/gearman-job-server/gearman.log
</span><span class='line'>end script
</span></code></pre></td></tr></table></div></figure>


<h2>The Benefit</h2>

<p>Gearman will now respect the settings found in
<code>/etc/default/gearman-job-server</code>, allowing you to configure Gearman with
<a href="http://gearman.org/manual/job_server/#options">command line options</a> that you&rsquo;d otherwise have to add to the init script.
In the case of the Graph Story implementation, I&rsquo;m binding Gearman to localhost
and using MySQL as a persistent queue. Here&rsquo;s what that config file looks
like:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
</pre></td><td class='code'><pre><code class='diff'><span class='line'># This is a configuration file for /etc/init.d/gearman-job-server; it allows
</span><span class='line'># you to perform common modifications to the behavior of the gearman-job-server
</span><span class='line'># daemon startup without editing the init script (and thus getting prompted by
</span><span class='line'># dpkg on upgrades).  We all love dpkg prompts.
</span><span class='line'>
</span><span class='line'># Examples ( from http://gearman.org/index.php?id=manual:job_server )
</span><span class='line'>#
</span><span class='line'># Use drizzle as persistent queue store
</span><span class='line'># PARAMS=&quot;-q libdrizzle --libdrizzle-db=some_db --libdrizzle-table=gearman_queue&quot;
</span><span class='line'>#
</span><span class='line'># Use mysql as persistent queue store
</span><span class='line'># PARAMS=&quot;-q libdrizzle --libdrizzle-host=10.0.0.1 --libdrizzle-user=gearman \
</span><span class='line'>#                       --libdrizzle-password=secret --libdrizzle-db=some_db \
</span><span class='line'>#                       --libdrizzle-table=gearman_queue --libdrizzle-mysql&quot;
</span><span class='line'>#
</span><span class='line'># Missing examples for memcache persitent queue store...
</span><span class='line'>
</span><span class='line'># Parameters to pass to gearmand.
</span><span class='line'>PARAMS=&quot;--listen=localhost \
</span><span class='line'>        -q mysql \
</span><span class='line'>        --mysql-host=localhost \
</span><span class='line'>        --mysql-port=3306 \
</span><span class='line'>        --mysql-user=redacted \
</span><span class='line'>        --mysql-password=redacted \
</span><span class='line'>        --mysql-db=gearman \
</span><span class='line'>        --mysql-table=gearman_queue&quot;
</span></code></pre></td></tr></table></div></figure>


<h2>Side Note and Pro Tip: MySQL Persistent Queue</h2>

<p>Creating the MySQL database and providing privileges to your database user allows
Gearman to create its own <code>gearman_queue</code> database table.  Don&rsquo;t risk creating an incompatible
database table; let Gearman do that work for you.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[From Zero to Slim Framework: Getting Your First Project Off the Ground]]></title>
    <link href="https://jeremykendall.net/2014/07/28/from-zero-to-slim-framework-getting-your-first-project-off-the-ground/"/>
    <updated>2014-07-28T11:19:01-05:00</updated>
    <id>https://jeremykendall.net/2014/07/28/from-zero-to-slim-framework-getting-your-first-project-off-the-ground</id>
    <content type="html"><![CDATA[<p>When I was a brand new web developer, I was overwhelmed by the amount of general
knowledge required to get a project off the ground: Web server (as in
configuring a server OS), web server (as in nginx or Apache), PHP installation,
PHP configuration, application configuration, and so forth.  I was willing and
able to learn, but even the best blog posts and documentation frequently assumed a certain level of
existing knowledge, much of which I didn&rsquo;t have. My goal with this post is to help you
get your first <a href="http://www.slimframework.com/">Slim Framework</a> project started
<em>without</em> assuming any knowledge on your part. We&rsquo;ll literally go from
absolutely nothing to a functioning <a href="https://github.com/codeguy/Slim-Skeleton">Slim-Skeleton</a>
application.</p>

<h3>Requirements</h3>

<p>While I&rsquo;m not going to make any general knowledge assumptions (call me out in
the comments if I miss the mark), I am going to set a few requirements.  In
short, we&rsquo;ll be using virtualization technology (<a href="http://www.vagrantup.com/">Vagrant</a>
and <a href="https://www.virtualbox.org/">VirtualBox</a>), the <a href="http://www.ubuntu.com/">Ubuntu</a>
14.04 LTS operating system, and <a href="https://getcomposer.org/">Composer</a>, a dependency
management tool for PHP.</p>

<h3>Why Do This All &ldquo;By Hand&rdquo;?</h3>

<p>While there&rsquo;s an &ldquo;easier, softer way&rdquo; (think <a href="http://phansible.com/">Phansible</a> or
<a href="https://puphpet.com/">PuPHPet</a>), I think it&rsquo;s important to know what&rsquo;s going
on behind the scenes.  What if you need to fix something on your server once
it&rsquo;s in production?  What if you have to tweak a setting here or there, or
create a new vhost or nginx site?  It&rsquo;s a good idea to have done it at least
once by hand before moving on to automated solutions.  You&rsquo;ll have a better
feel for what&rsquo;s happening, why it&rsquo;s happening, and how to fix any problems that
might arise in the future.</p>

<h3>Preparing the Host Environment</h3>

<p>By &ldquo;host&rdquo;, I mean your computer.  These are the first steps we&rsquo;ll take to prepare your
computer to host the virtual machine we&rsquo;ll use to run the tutorial code.</p>

<ul>
<li>Install Vagrant: Grab an installer for your OS <a href="http://www.vagrantup.com/downloads.html">here</a>.</li>
<li>Install VirtualBox: Grab an installer for your OS <a href="https://www.virtualbox.org/wiki/Downloads">here</a>.</li>
</ul>


<h3>Create Your VM</h3>

<ul>
<li>Create a directory for your project, and then change into your project directory</li>
<li>Make a sub-directory for your Slim project within your new project directory: <code>mkdir zero-to-slim.dev</code></li>
<li>Now run <code>vagrant init ubuntu/trusty64</code> from your project directory</li>
</ul>


<p><code>vagrant init</code> will create a <code>Vagrantfile</code>, the file that tells Vagrant how to
build your VM.  We&rsquo;ll need to edit that file and add a few settings.</p>

<p>Edit <code>/path/to/project/Vagrantfile</code> and add the following lines after <code>config.vm.box</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">hostname</span> <span class="o">=</span> <span class="s2">&quot;zero-to-slim.dev&quot;</span>
</span><span class='line'>  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">network</span> <span class="ss">:private_network</span><span class="p">,</span> <span class="ss">ip</span><span class="p">:</span> <span class="s2">&quot;192.168.56.103&quot;</span>
</span><span class='line'>  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">synced_folder</span> <span class="s2">&quot;./zero-to-slim.dev&quot;</span><span class="p">,</span> <span class="s2">&quot;/var/www/zero-to-slim.dev&quot;</span><span class="p">,</span> <span class="nb">id</span><span class="p">:</span> <span class="s2">&quot;web-root&quot;</span><span class="p">,</span>
</span><span class='line'>      <span class="ss">owner</span><span class="p">:</span> <span class="s2">&quot;vagrant&quot;</span><span class="p">,</span>
</span><span class='line'>      <span class="ss">group</span><span class="p">:</span> <span class="s2">&quot;www-data&quot;</span><span class="p">,</span>
</span><span class='line'>      <span class="n">mount_options</span><span class="p">:</span> <span class="o">[</span><span class="s2">&quot;dmode=775,fmode=664&quot;</span><span class="o">]</span>
</span></code></pre></td></tr></table></div></figure>


<p>Save and close your <code>Vagrantfile</code>, and then run <code>vagrant up</code>.  You&rsquo;ll be treated
to some output as your VM is built.  Once that&rsquo;s done, the VM is ready to configure.</p>

<h3>Connect and Configure VM</h3>

<p>Run <code>vagrant ssh</code> from your project directory.  The following steps will be
completed on the VM, not your host machine.</p>

<blockquote><p>If you&rsquo;re on Windows, the <code>ssh</code> command won&rsquo;t be available to you.  You&rsquo;ll need
to use a program like <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/">PuTTY</a>
instead. Here are some <a href="https://github.com/Varying-Vagrant-Vagrants/VVV/wiki/Connect-to-Your-Vagrant-Virtual-Machine-with-PuTTY">step-by-step instructions</a>
for configuring your Windows box to connect to your new VM.</p></blockquote>

<ul>
<li><code>sudo apt-get update</code></li>
<li><code>sudo apt-get install curl vim wget python-software-properties -y</code></li>
<li><code>sudo add-apt-repository ppa:ondrej/php5 -y</code></li>
<li><code>sudo apt-get update</code></li>
</ul>


<h3>Choose a Web Server and a PHP Version</h3>

<blockquote><p>You must choose one or the other, not both. nginx is extremely
popular, but if you&rsquo;re more comfortable with Apache I&rsquo;ve included instructions
below.</p></blockquote>

<h4>nginx and PHP-FPM</h4>

<ul>
<li><code>sudo apt-get install php5-fpm php5-cli php5-xdebug nginx -y</code></li>
</ul>


<h4>Apache2 and PHP</h4>

<ul>
<li><code>sudo apt-get install php5 php5-cli php5-xdebug apache2 -y</code></li>
</ul>


<h3>Install Composer Globally</h3>

<p>See Composer&rsquo;s <a href="https://getcomposer.org/doc/00-intro.md">Getting Started</a>
section for the most up-to-date installation instructions (There&rsquo;s an
<a href="https://getcomposer.org/doc/00-intro.md#installation-windows">installer available</a>
for those of you on Windows). Below is how I install Composer on both Mac and Linux.</p>

<ul>
<li><code>curl -sS https://getcomposer.org/installer | php</code></li>
<li><code>sudo mv composer.phar /usr/local/bin/composer</code></li>
</ul>


<h3>Use Composer to Install Slim Skeleton</h3>

<p>Heads up, this is going to take a while.  Composer is an amazing technology,
but in this case it&rsquo;s pretty slow (this has more to do with the VM than with
Composer). Run the command, grab a cup of coffee, and come on back to finish
up.</p>

<ul>
<li><code>composer create-project slim/slim-skeleton /var/www/zero-to-slim.dev</code></li>
</ul>


<blockquote><p>If you suspect there&rsquo;s a problem with the <code>composer create-project</code> command
due to how long it takes to get feedback, you can add the verbose option
(<code>-vvv</code>) to the command, like so: <code>composer create-project slim/slim-skeleton /var/www/zero-to-slim.dev -vvv</code></p></blockquote>

<h3>Configure Your Web Server</h3>

<p>Since the following files aren&rsquo;t in a synced folder, which would allow you to edit them
from your host machine, and since you need to be root to edit them, the best
way to do so is directly on the server using a text editor. I&rsquo;ve chosen
<a href="http://www.vim.org/">Vim</a> in this case. Once again, here&rsquo;s an opportunity to
learn about a tool that you may find yourself needing at some point in the
future, even if you only ever use it to edit a file or two on your server(s).</p>

<h4>Editing a Config File with Vim</h4>

<ul>
<li>Type <code>sudo vim &lt;server_config_file&gt;</code> (either <code>/etc/nginx/sites-available/default</code> or
<code>/etc/apache2/sites-available/000-default.conf</code>, depending)</li>
<li>Type <code>gg</code> on the keyboard to ensure you&rsquo;re at the top of the file</li>
<li>Delete everything in the file with <code>dG</code></li>
<li>Type <code>i</code> to enter insert mode</li>
<li>Copy the appropriate config from below and paste it into the config document</li>
<li>Hit <code>ESC</code> to exit insert mode</li>
<li>Type <code>:wq</code> to write your changes and quit the file.</li>
</ul>


<p>Congrats! You&rsquo;ve just edited your server config using Vim, an accomplishment in itself.</p>

<h4>nginx and PHP-FPM</h4>

<p>Replace the contents of <code>/etc/nginx/sites-available/default</code> with the following:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='nginx'><span class='line'><span class="k">server</span> <span class="p">{</span>
</span><span class='line'>    <span class="kn">listen</span>      <span class="mi">80</span><span class="p">;</span>
</span><span class='line'>    <span class="kn">server_name</span> <span class="s">zero-to-slim.dev</span><span class="p">;</span>
</span><span class='line'>    <span class="kn">root</span>        <span class="s">/var/www/zero-to-slim.dev/public</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="kn">try_files</span> <span class="nv">$uri</span> <span class="s">/index.php</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># this will only pass index.php to the fastcgi process which is generally safer but</span>
</span><span class='line'>    <span class="c1"># assumes the whole site is run via Slim.</span>
</span><span class='line'>    <span class="kn">location</span> <span class="s">/index.php</span> <span class="p">{</span>
</span><span class='line'>        <span class="kn">fastcgi_connect_timeout</span> <span class="s">3s</span><span class="p">;</span>     <span class="c1"># default of 60s is just too long</span>
</span><span class='line'>        <span class="kn">fastcgi_read_timeout</span> <span class="s">10s</span><span class="p">;</span>       <span class="c1"># default of 60s is just too long</span>
</span><span class='line'>        <span class="kn">fastcgi_pass</span> <span class="s">unix:/var/run/php5-fpm.sock</span><span class="p">;</span>
</span><span class='line'>        <span class="kn">include</span> <span class="s">fastcgi_params</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Save and close the default config, and then restart nginx: <code>sudo service nginx restart</code></p>

<h4>Apache2</h4>

<p>Replace the contents of <code>/etc/apache2/sites-available/000-default.conf</code> with the following:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='apache'><span class='line'><span class="nt">&lt;VirtualHost</span> <span class="s">*:80</span><span class="nt">&gt;</span>
</span><span class='line'>    <span class="nb">DocumentRoot</span> <span class="s2">&quot;/var/www/zero-to-slim.dev/public&quot;</span>
</span><span class='line'>    <span class="nb">ServerName</span> zero-to-slim.dev
</span><span class='line'>
</span><span class='line'>    <span class="nt">&lt;Directory</span> <span class="s">&quot;/var/www/zero-to-slim.dev/public&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>        <span class="nb">AllowOverride</span> <span class="k">All</span>
</span><span class='line'>        <span class="nb">Order</span> allow,deny
</span><span class='line'>        <span class="nb">Allow</span> from <span class="k">all</span>
</span><span class='line'>    <span class="nt">&lt;/Directory&gt;</span>
</span><span class='line'><span class="nt">&lt;/VirtualHost&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>Save and close the default config</li>
<li>Enable <code>mod_rewrite</code> for URL rewriting: <code>sudo a2enmod rewrite</code></li>
<li>Restart Apache: <code>sudo service apache2 restart</code></li>
</ul>


<h3>Configure PHP for Dev Environment</h3>

<p>Since editing <code>php.ini</code> with Vim would require quite a few detailed
instructions, I&rsquo;ve opted to show you how to override <code>php.ini</code> settings by
adding an additional config file.</p>

<p>On your host machine, create a file in your project directory name <code>00-php.ini</code>.
Paste the following contents into the file:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='apache'><span class='line'><span class="nb">error_reporting</span> = -1
</span><span class='line'><span class="nb">display_errors</span> = <span class="k">On</span>
</span><span class='line'><span class="nb">display_startup_errors</span> = <span class="k">On</span>
</span><span class='line'><span class="nb">html_errors</span> = <span class="k">On</span>
</span></code></pre></td></tr></table></div></figure>


<p>These settings ensure that PHP will report any and all errors it encounters,
and that PHP will display those errors on screen.  The <code>html_errors</code> setting
will provide a nice looking error formatted by <code>xdebug</code>.</p>

<p>Since your project directory is synced to <code>/vagrant</code> on your VM, the file you just
created will be available on your VM.  Copy the new config file into the directory
scanned by PHP for additional config files and restart your web server. The
following commands should be executed on your VM, not your host machine.</p>

<h4>nginx and PHP-FPM</h4>

<ul>
<li><code>sudo cp /vagrant/00-php.ini /etc/php5/fpm/conf.d/</code></li>
<li><code>sudo service php5-fpm restart</code></li>
</ul>


<h4>Apache2 and PHP</h4>

<ul>
<li><code>sudo cp /vagrant/00-php.ini /etc/php5/apache2/conf.d/</code></li>
<li><code>sudo service apache2 restart</code></li>
</ul>


<h3>Final Configuration</h3>

<ul>
<li>Add <code>192.168.56.103 zero-to-slim.dev</code> to <code>/etc/hosts</code> on the host machine
(Windows users, see: <a href="http://www.rackspace.com/knowledge_center/article/how-do-i-modify-my-hosts-file">How do I modify my hosts file</a>)</li>
<li>Visit <a href="http://zero-to-slim.dev">http://zero-to-slim.dev</a> in your web browser</li>
</ul>


<p>You should see the Slim welcome page.  If you don&rsquo;t, there should be an error
displayed telling you exactly what went wrong.  Double check the steps above to make
sure you didn&rsquo;t miss anything. If you still have problems, drop me a line in the comments and
I&rsquo;ll help you get them sorted out.</p>

<h3>Wrapping Up</h3>

<p>So there you have it.  You started with nothing at all and now have a working
Slim Framework application. Congrats!</p>

<p>FYI, I highly recommend basing your Slim apps on the Slim Skeleton.  Install
it, modify it for your specific application needs, and you&rsquo;ll have a much
easier time getting up and running, I promise. That&rsquo;s what I did when I first
started with Slim.</p>

<blockquote><p>Next time we&rsquo;ll talk about how to automate this process.  Now that you know what&rsquo;s
involved, there&rsquo;s no point in wasting precious dev time manually configuring
new machines for each new project.</p></blockquote>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Composer Platform Packages]]></title>
    <link href="https://jeremykendall.net/2014/03/08/composer-platform-packages/"/>
    <updated>2014-03-08T18:36:22-06:00</updated>
    <id>https://jeremykendall.net/2014/03/08/composer-platform-packages</id>
    <content type="html"><![CDATA[<p>Here&rsquo;s something about Composer that I can never remember, I always have to
look up, and I always have a hard time finding where it is in the
documentation. Ladies and gentlemen, I give you <a href="https://getcomposer.org/doc/02-libraries.md#platform-packages">platform packages</a>:</p>

<blockquote><h2>Platform packages</h2>

<p>Composer has platform packages, which are virtual packages for things that are
installed on the system but are not actually installable by Composer. This
includes PHP itself, PHP extensions and some system libraries.</p>

<ul>
<li><p><code>php</code> represents the PHP version of the user, allowing you to apply
constraints, e.g. <code>&gt;=5.4.0</code>. To require a 64bit version of php, you can
require the <code>php-64bit</code> package.</p></li>
<li><p><code>hhvm</code> represents the version of the HHVM runtime (aka HipHop Virtual
Machine) and allows you to apply a constraint, e.g., &lsquo;>=2.3.3&rsquo;.</p></li>
<li><p><code>ext-&lt;name&gt;</code> allows you to require PHP extensions (includes core
extensions). Versioning can be quite inconsistent here, so it&rsquo;s often
a good idea to just set the constraint to <code>*</code>.  An example of an extension
package name is <code>ext-gd</code>.</p></li>
<li><p><code>lib-&lt;name&gt;</code> allows constraints to be made on versions of libraries used by
PHP. The following are available: <code>curl</code>, <code>iconv</code>, <code>icu</code>, <code>libxml</code>,
<code>openssl</code>, <code>pcre</code>, <code>uuid</code>, <code>xsl</code>.</p></li>
</ul>


<p>You can use <code>composer show --platform</code> to get a list of your locally available
platform packages.</p></blockquote>

<p>So that&rsquo;s the relevant portion of the documentation, and its <code>composer show --platform</code> that lists local platform packages. Maybe <em>now</em> I&rsquo;ll remember.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[PHP Password Hashing: A Dead Simple Implementation]]></title>
    <link href="https://jeremykendall.net/2014/01/04/php-password-hashing-a-dead-simple-implementation/"/>
    <updated>2014-01-04T01:55:10-06:00</updated>
    <id>https://jeremykendall.net/2014/01/04/php-password-hashing-a-dead-simple-implementation</id>
    <content type="html"><![CDATA[<h4>[UPDATE: Added a new section at the end of the post]</h4>

<h4>[UPDATE 2: Added a section RE: StorageDecorator]</h4>

<p><strong>tl;dr</strong>: Install <a href="https://packagist.org/packages/jeremykendall/password-validator">Password Validator</a> and all of your password troubles
will be solved.  All of them.  It&rsquo;ll even upgrade your old hashes
transparently. Sup?</p>

<h2>Hashing Done Wrong</h2>

<p>We all know to <a href="http://csiphp.com/blog/2012/02/16/encrypt-passwords-for-highest-level-of-security/">encrypt passwords for highest level of security</a>.
Unfortunately, too many do it like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">class</span> <span class="nc">SecurityFail</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>    <span class="c1">// Encrypt Passwords for Highest Level of Security.</span>
</span><span class='line'>    <span class="k">static</span> <span class="k">public</span> <span class="k">function</span> <span class="nf">encrypt</span><span class="p">(</span><span class="nv">$pword</span><span class="p">)</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="nb">md5</span><span class="p">(</span><span class="nv">$pword</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>While there was never any excuse for getting it <em>that</em> wrong, there&rsquo;s now no
excuse for getting it wrong at all. Developers, meet the new(-ish)
<a href="http://www.php.net/manual/en/ref.password.php">PHP password hashing</a> functions (and the userland implementation <a href="https://github.com/ircmaxell/password_compat">password-compat</a>).</p>

<h2>Hashing Done Right</h2>

<p>First, alter the password column in your user database to <code>VARCHAR(255)</code>.
Current <code>BCRYPT</code> passwords are 60 characters in length, but when PHP upgrades
the default hash (which will happen at some point), you want to be ready.
Really, just do it.</p>

<p>When it&rsquo;s time to create a new user password, throw the plain text password
into <a href="http://www.php.net/manual/en/function.password-hash.php"><code>password_hash()</code></a>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nv">$hash</span> <span class="o">=</span> <span class="nx">password_hash</span><span class="p">(</span><span class="nv">$plainTextPassword</span><span class="p">,</span> <span class="nx">PASSWORD_DEFAULT</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>The next time a user logs in, use a little <a href="http://www.php.net/manual/en/function.password-verify.php"><code>password_verify()</code></a> action:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nv">$isValid</span> <span class="o">=</span> <span class="nx">password_verify</span><span class="p">(</span><span class="nv">$plainTextPassword</span><span class="p">,</span> <span class="nv">$hashedPassword</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>If the password is valid, check to see if it needs to be rehashed with
<a href="http://www.php.net/manual/en/function.password-needs-rehash.php"><code>password_needs_rehash()</code></a>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nv">$needsRehash</span> <span class="o">=</span> <span class="nx">password_needs_rehash</span><span class="p">(</span><span class="nv">$hashedPassword</span><span class="p">,</span> <span class="nx">PASSWORD_DEFAULT</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>If the password needs to be rehashed, run it through <code>password_hash()</code> again
and persist the result.</p>

<p>Trivial, right? Right!</p>

<h2>Even Trivial-er</h2>

<p>Since implementing the code above might take as many as two or three hours out
of your day, I went ahead and implemented it for you. Behold, Password
Validator!</p>

<h2>Password Validator</h2>

<p>The <a href="https://packagist.org/packages/jeremykendall/password-validator">Password Validator</a> library <em>validates</em> <code>password_hash</code> generated
passwords, <em>rehashes</em> passwords as necessary, and can <em>upgrade</em> legacy
passwords (if configured to do so).</p>

<p>The really big deal here is the <strong>ease of upgrading</strong> from your current legacy
hashes to the new, more secure, PHP generated hashes. More on that later.</p>

<h2>Usage</h2>

<h3>Password Validation</h3>

<p>If you&rsquo;re already using <a href="http://www.php.net/manual/en/function.password-hash.php"><code>password_hash</code></a> generated passwords in your
application, you need do nothing more than add the validator in your
authentication script. The validator uses <a href="http://www.php.net/manual/en/function.password-verify.php"><code>password_verify</code></a> to test
the validity of the provided password hash.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">use</span> <span class="nx">JeremyKendall\Password\PasswordValidator</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$validator</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">PasswordValidator</span><span class="p">();</span>
</span><span class='line'><span class="nv">$result</span> <span class="o">=</span> <span class="nv">$validator</span><span class="o">-&gt;</span><span class="na">isValid</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">&#39;password&#39;</span><span class="p">],</span> <span class="nv">$hashedPassword</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="p">(</span><span class="nv">$result</span><span class="o">-&gt;</span><span class="na">isValid</span><span class="p">())</span> <span class="p">{</span>
</span><span class='line'>    <span class="c1">// password is valid</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>If your application requires options other than the <code>password_hash</code> defaults,
you can set both the <code>salt</code> and <code>cost</code> options with <code>PasswordValidator::setOptions()</code>.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nv">$options</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>    <span class="s1">&#39;salt&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;SettingYourOwnSaltIsNotTheBestIdea&#39;</span><span class="p">,</span>
</span><span class='line'>    <span class="s1">&#39;cost&#39;</span> <span class="o">=&gt;</span> <span class="mi">11</span><span class="p">,</span>
</span><span class='line'><span class="p">);</span>
</span><span class='line'><span class="nv">$validator</span><span class="o">-&gt;</span><span class="na">setOptions</span><span class="p">(</span><span class="nv">$options</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p><strong>IMPORTANT</strong>: <code>PasswordValidator</code> uses a default cost of <code>10</code>. If your
existing hash implementation requires a different cost, make sure to specify it
using <code>PasswordValidator::setOptions()</code>. If you do not do so, all of your
passwords will be rehashed using a cost of <code>10</code>.</p>

<h3>Rehashing</h3>

<p>Each valid password is tested using <a href="http://www.php.net/manual/en/function.password-needs-rehash.php"><code>password_needs_rehash</code></a>. If a rehash
is necessary, the valid password is rehashed using <code>password_hash</code> with the
provided options. The result code <code>Result::SUCCESS_PASSWORD_REHASHED</code> will be
returned from <code>Result::getCode()</code> and the rehashed password is available via
<code>Result::getPassword()</code>.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">if</span> <span class="p">(</span><span class="nv">$result</span><span class="o">-&gt;</span><span class="na">isValid</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="nv">$result</span><span class="o">-&gt;</span><span class="na">getCode</span><span class="p">()</span> <span class="o">==</span> <span class="nx">Result</span><span class="o">::</span><span class="na">SUCCESS_PASSWORD_REHASHED</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nv">$rehashedPassword</span> <span class="o">=</span> <span class="nv">$result</span><span class="o">-&gt;</span><span class="na">getPassword</span><span class="p">();</span>
</span><span class='line'>    <span class="c1">// Persist rehashed password</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p><strong>IMPORTANT</strong>: If the password has been rehashed, it&rsquo;s critical that you
persist the updated password hash. Otherwise, what&rsquo;s the point, right?</p>

<h3>Upgrading Legacy Passwords</h3>

<p>You can use the <code>PasswordValidator</code> whether or not you&rsquo;re currently using
<code>password_hash</code> generated passwords. The validator will upgrade your current
legacy hashes to the new <code>password_hash</code> generated hashes.  All you need to
do is provide a validator callback for your password hashing scheme and then
<a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorate</a> the validator with the <code>UpgradeDecorator</code>.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">use</span> <span class="nx">JeremyKendall\Password\Decorator\UpgradeDecorator</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// Example callback to validate a sha512 hashed password</span>
</span><span class='line'><span class="nv">$callback</span> <span class="o">=</span> <span class="k">function</span> <span class="p">(</span><span class="nv">$password</span><span class="p">,</span> <span class="nv">$passwordHash</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="nb">hash</span><span class="p">(</span><span class="s1">&#39;sha512&#39;</span><span class="p">,</span> <span class="nv">$password</span><span class="p">)</span> <span class="o">===</span> <span class="nv">$passwordHash</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">return</span> <span class="k">false</span><span class="p">;</span>
</span><span class='line'><span class="p">};</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$validator</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">UpgradeDecorator</span><span class="p">(</span><span class="k">new</span> <span class="nx">PasswordValidator</span><span class="p">(),</span> <span class="nv">$callback</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>The <code>UpgradeDecorator</code> will validate a user&rsquo;s current password using the
callback.  If the user&rsquo;s password is valid, it will be hashed with
<code>password_hash</code> and returned in the <code>Result</code> object, as above.</p>

<p>If the callback determines the password is invalid, the password will be passed
along to the <code>PasswordValidator</code> in case it&rsquo;s already been upgraded.</p>

<h3>Persisting Rehashed Passwords</h3>

<p>Whenever a validation attempt returns <code>Result::SUCCESS_PASSWORD_REHASHED</code>, it&rsquo;s
important to persist the updated password hash.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">if</span> <span class="p">(</span><span class="nv">$result</span><span class="o">-&gt;</span><span class="na">getCode</span><span class="p">()</span> <span class="o">===</span> <span class="nx">Result</span><span class="o">::</span><span class="na">SUCCESS_PASSWORD_REHASHED</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nv">$rehashedPassword</span> <span class="o">=</span> <span class="nv">$result</span><span class="o">-&gt;</span><span class="na">getPassword</span><span class="p">();</span>
</span><span class='line'>    <span class="c1">// Persist rehashed password</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>While you can always perform the test and then update your user database
manually, if you choose to use the <strong>Storage Decorator</strong> all rehashed passwords
will be automatically persisted.</p>

<p>The Storage Decorator takes two constructor arguments: An instance of
<code>PasswordValidatorInterface</code> and an instance of the
<code>JeremyKendall\Password\Storage\StorageInterface</code>.</p>

<h4>StorageInterface</h4>

<p>The <code>StorageInterface</code> includes a single method, <code>updatePassword()</code>. A class
honoring the interface might look like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="o">&lt;?</span><span class="nx">php</span>
</span><span class='line'>
</span><span class='line'><span class="k">namespace</span> <span class="nx">Example</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">use</span> <span class="nx">JeremyKendall\Password\Storage\StorageInterface</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">UserDao</span> <span class="k">implements</span> <span class="nx">StorageInterface</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">__construct</span><span class="p">(</span><span class="nx">\PDO</span> <span class="nv">$db</span><span class="p">)</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">db</span> <span class="o">=</span> <span class="nv">$db</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">public</span> <span class="k">function</span> <span class="nf">updatePassword</span><span class="p">(</span><span class="nv">$identity</span><span class="p">,</span> <span class="nv">$password</span><span class="p">)</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="nv">$sql</span> <span class="o">=</span> <span class="s1">&#39;UPDATE users SET password = :password WHERE username = :identity&#39;</span><span class="p">;</span>
</span><span class='line'>        <span class="nv">$stmt</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">db</span><span class="o">-&gt;</span><span class="na">prepare</span><span class="p">(</span><span class="nv">$sql</span><span class="p">);</span>
</span><span class='line'>        <span class="nv">$stmt</span><span class="o">-&gt;</span><span class="na">execute</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;password&#39;</span> <span class="o">=&gt;</span> <span class="nv">$password</span><span class="p">,</span> <span class="s1">&#39;username&#39;</span> <span class="o">=&gt;</span> <span class="nv">$identity</span><span class="p">));</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h4>Storage Decorator</h4>

<p>With your <code>UserDao</code> in hand, you&rsquo;re ready to decorate a
<code>PasswordValidatorInterface</code>.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">use</span> <span class="nx">Example\UserDao</span><span class="p">;</span>
</span><span class='line'><span class="k">use</span> <span class="nx">JeremyKendall\Password\Decorator\StorageDecorator</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$storage</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">UserDao</span><span class="p">(</span><span class="nv">$db</span><span class="p">);</span>
</span><span class='line'><span class="nv">$validator</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">StorageDecorator</span><span class="p">(</span><span class="k">new</span> <span class="nx">PasswordValidator</span><span class="p">(),</span> <span class="nv">$storage</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// If validation results in a rehash, the new password hash will be persisted</span>
</span><span class='line'><span class="nv">$result</span> <span class="o">=</span> <span class="nv">$validator</span><span class="o">-&gt;</span><span class="na">isValid</span><span class="p">(</span><span class="s1">&#39;password&#39;</span><span class="p">,</span> <span class="s1">&#39;passwordHash&#39;</span><span class="p">,</span> <span class="s1">&#39;username&#39;</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p><strong>IMPORTANT</strong>: You must pass the optional third argument (<code>$identity</code>) to
<code>isValid()</code> when calling <code>StorageDecorator::isValid()</code>.  If you do not do so,
the <code>StorageDecorator</code> will throw an <code>IdentityMissingException</code>.</p>

<h3>Validation Results</h3>

<p>Each validation attempt returns a <code>Result</code> object. The object provides some
introspection into the status of the validation process.</p>

<ul>
<li><code>Result::isValid()</code> will return <code>true</code> if the attempt was successful</li>
<li><code>Result::getCode()</code> will return one of three possible <code>int</code> codes:

<ul>
<li><code>Result::SUCCESS</code> if the validation attempt was successful</li>
<li><code>Result::SUCCESS_PASSWORD_REHASHED</code> if the attempt was successful and the password was rehashed</li>
<li><code>Result::FAILURE_PASSWORD_INVALID</code> if the attempt was unsuccessful</li>
</ul>
</li>
<li><code>Result::getPassword()</code> will return the rehashed password, but only if the password was rehashed</li>
</ul>


<h3>Database Schema Changes</h3>

<p>As mentioned above, because this library uses the <code>PASSWORD_DEFAULT</code> algorithm,
it&rsquo;s important your password field be <code>VARCHAR(255)</code> to account for future
updates to the default password hashing algorithm.</p>

<h2>Helper Scripts</h2>

<p>There are two helper scripts available, both related to the password hash
functions (these functions are only available after running <code>composer
install</code>).</p>

<h3>version-check</h3>

<p>If you&rsquo;re not already running PHP 5.5+, you should run <code>version-check</code> to
ensure your version of PHP is capable of using password-compat, the userland
implementation of the PHP password hash functions.  Run <code>./vendor/bin/version-check</code>
from the root of your project. The result of the script is pass/fail.</p>

<h3>cost-check</h3>

<p>The default <code>cost</code> used by <code>password_hash</code> is 10.  This may or may not be
appropriate for your production hardware, and it&rsquo;s entirely likely you can use
a higher cost than the default. <code>cost-check</code> is based on the <a href="http://php.net/password_hash#example-875">finding a good
cost</a> example in the PHP documentation. Simply run <code>./vendor/bin/cost-check</code> from the command line and an appropriate cost will be returned.</p>

<p><strong>NOTE</strong>: The default time target is 0.2 seconds.  You may choose a higher or lower
target by passing a float argument to <code>cost-check</code>, like so:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>./vendor/bin/cost-check 0.4
</span><span class='line'>Appropriate <span class="s1">&#39;PASSWORD_DEFAULT&#39;</span> Cost Found:  13
</span></code></pre></td></tr></table></div></figure>


<h2>Wrapping Up</h2>

<p>The addition of native <a href="http://www.php.net/manual/en/ref.password.php">password hashing functions</a> is the most important
security update to PHP since, well, I don&rsquo;t know when. There&rsquo;s no excuse for
not implementing them in your applications, and the <a href="https://packagist.org/packages/jeremykendall/password-validator">Password Validator</a>
library makes it trivial. That&rsquo;s especially true when it comes to updating your
legacy password hashes, which many of us need to do.  Even if you only use the
Password Validator as a roadmap for your own implementation, I strongly
recommend upgrading ASAP.</p>

<h2>Kudos</h2>

<p>I was remiss to not add this bit of kudos when I originally published this
post.  Better late than never.</p>

<p>Credit for the new password hashing functions goes to <a href="https://twitter.com/ircmaxell">Anthony Ferrara</a>.
He submitted the <a href="https://wiki.php.net/rfc/password_hash">original RFC</a> and created the <a href="https://github.com/ircmaxell/password_compat">password-compat</a>
library. The PHP community owes Anthony a debt of gratitude for making password
hash security so ridiculously simple.  Seriously, if <em>I</em> can grok it, you
know it&rsquo;s idiot proof :-)</p>

<p>Without Anthony&rsquo;s hard work (and <a href="https://wiki.php.net/rfc/password_hash#vote">PHP core&rsquo;s unanimous &lsquo;Yes&rsquo; votes</a>, and
the <a href="https://github.com/ircmaxell/password_compat/graphs/contributors">password-compat contributors</a>), my small contribution wouldn&rsquo;t have
been possible.  Kudos to you all.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Installing Phpass From Openwall via Composer]]></title>
    <link href="https://jeremykendall.net/2013/12/13/installing-phpass-from-openwall-via-composer/"/>
    <updated>2013-12-13T13:05:29-06:00</updated>
    <id>https://jeremykendall.net/2013/12/13/installing-phpass-from-openwall-via-composer</id>
    <content type="html"><![CDATA[<p><strong>[UPDATE: Added a PHP version clarification at the end of the post.]</strong></p>

<p>Managing dependencies via <a href="http://getcomposer.org">Composer</a> is one of the most
revolutionary advancements in the history of PHP. Composer packages are frequently
hosted on <a href="http://github.com">Github</a>, listed on
<a href="https://packagist.org/">Packagist</a>, and required in your project via the
<a href="http://getcomposer.org/doc/04-schema.md#package-links">require field</a> in <code>composer.json</code>.</p>

<h2>So Where is phpass?</h2>

<p>What happens when that&rsquo;s not the case?  One library of note,
<a href="http://www.openwall.com/phpass/">phpass</a>, is not available on Github (or any
other supported VCS)<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> and therefore can&rsquo;t simply be added to the <code>require</code>
field for easy installation. All is not lost, however, thanks to Composer&rsquo;s
<a href="http://getcomposer.org/doc/05-repositories.md#package-2">package repository</a>
feature<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>.</p>

<h2>Behold, Composer&rsquo;s &lsquo;Package&rsquo; Repository!</h2>

<p>After reviewing the package repository docs, I found it ridiculously easy to require
phpass in my project. Here&rsquo;s what you have to do.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="p">{</span>
</span><span class='line'>    <span class="s2">&quot;repositories&quot;</span><span class="o">:</span> <span class="p">[</span>
</span><span class='line'>    <span class="p">{</span>
</span><span class='line'>        <span class="s2">&quot;type&quot;</span><span class="o">:</span> <span class="s2">&quot;package&quot;</span><span class="p">,</span>
</span><span class='line'>        <span class="s2">&quot;package&quot;</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>            <span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;openwall/phpass&quot;</span><span class="p">,</span>
</span><span class='line'>            <span class="s2">&quot;version&quot;</span><span class="o">:</span> <span class="s2">&quot;0.3&quot;</span><span class="p">,</span>
</span><span class='line'>            <span class="s2">&quot;dist&quot;</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>                <span class="s2">&quot;url&quot;</span><span class="o">:</span> <span class="s2">&quot;http://www.openwall.com/phpass/phpass-0.3.tar.gz&quot;</span><span class="p">,</span>
</span><span class='line'>                <span class="s2">&quot;type&quot;</span><span class="o">:</span> <span class="s2">&quot;tar&quot;</span>
</span><span class='line'>            <span class="p">},</span>
</span><span class='line'>            <span class="s2">&quot;autoload&quot;</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>                <span class="s2">&quot;classmap&quot;</span><span class="o">:</span> <span class="p">[</span><span class="s2">&quot;PasswordHash.php&quot;</span><span class="p">]</span>
</span><span class='line'>            <span class="p">}</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="p">],</span>
</span><span class='line'>    <span class="s2">&quot;require&quot;</span><span class="o">:</span> <span class="p">{</span>
</span><span class='line'>        <span class="s2">&quot;openwall/phpass&quot;</span><span class="o">:</span> <span class="s2">&quot;0.3&quot;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now you can run <code>composer install</code> (or <code>composer update</code>, as appropriate) and Composer will install
phpass as a project dependency.  Sweet!</p>

<p><strong>UPDATE - CLARIFICATION</strong>: Using phpass is only advisable for PHP versions
that won&rsquo;t support the new password hashing functions.  That&rsquo;s any version of
PHP less than 5.3.7:</p>

<ul>
<li><strong>PHP >= 5.5</strong>: <a href="http://us3.php.net/manual/en/ref.password.php">Password hashing functions</a> available natively</li>
<li><strong>PHP >= 5.3.7, &lt; 5.5</strong>: <a href="https://github.com/ircmaxell/password_compat">password_compat</a> provides forward compatibility</li>
<li><strong>PHP &lt; 5.3.7</strong>: phpass is the gold standard</li>
</ul>


<p>If you&rsquo;re at PHP >= 5.3.7, enjoy this article as a Composer tip you might not
have know about until now and use
<a href="https://github.com/ircmaxell/password_compat">password_compat</a>.  If you&rsquo;re at
PHP &lt; 5.3.7, this is both a Composer tip and an admonition to upgrade you
password security. Do it!</p>

<p><em>Many thanks to <a href="http://jeremykendall.net/2013/12/13/installing-phpass-from-openwall-via-composer/#comment-1191140568">Meroje</a>
and <a href="https://twitter.com/craig_bass/status/420666580129697792">@craig_bass</a> for
pointing out that password_compat is superior, making it clear that I needed to
post a clarification.</em></p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>Yes, there are phpass repos on Github, but Anthony Ferrara <a href="https://twitter.com/ircmaxell/status/411566597208170496">recommends against them</a>. When Anthony talks security, I listen.<a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
<li id="fn:2">
<p>Be aware, there are significant drawbacks to this method (noted at the bottom of the <a href="http://getcomposer.org/doc/05-repositories.md#package-2">Package documentation</a>), but sometimes it&rsquo;s the only way.<a href="#fnref:2" rev="footnote">&#8617;</a></p></li>
</ol>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Creating Case-insensitive Routes With the Slim Framework]]></title>
    <link href="https://jeremykendall.net/2013/12/11/creating-case-insensitive-routes-with-the-slim-framework/"/>
    <updated>2013-12-11T17:56:55-06:00</updated>
    <id>https://jeremykendall.net/2013/12/11/creating-case-insensitive-routes-with-the-slim-framework</id>
    <content type="html"><![CDATA[<p>This <a href="http://stackoverflow.com/questions/19953870/how-to-set-up-case-insensitive-routes-with-slim-framework/20532205#20532205">Stack Overflow question</a>
about case-insensitive routing with the Slim Framework caught my eye recently. The question asks, in part:</p>

<blockquote><p>How can I avoid setting up two separate routes [with different cases] that trigger the same callback function?</p></blockquote>

<p>I found the question intriguing because 1) I love Slim and 2) I&rsquo;ve never really
thought about whether or not URLs are case-sensitive to begin with.  My
immediate thought was, &ldquo;They&rsquo;re already case-insensitive! Has dude even tested this?&rdquo;</p>

<h2>Are URLs Case-sensitive?</h2>

<p>Well, kinda.  It frequently, but not always, boils down to whether or not the
web server&rsquo;s filesystem is case sensitive. The HTTP server (Apache, nginx, etc)
can get involved, as they can (always?) be configured to serve URLs with or
without regard to case sensitivity.  The web application and/or framework is
involved too.  If all other factors are case-insensitive but your application&rsquo;s
router is case-sensitive, then your application&rsquo;s URLs will be too. This is the
case with the Slim Framework.</p>

<h2>Should URLs Be Case-sensitive?</h2>

<p>Again, kinda.  In &ldquo;HTML and URLs&rdquo;, the <a href="http://www.w3.org/TR/WD-html40-970708/htmlweb.html">w3c has this to say</a>:</p>

<blockquote><p>URLs in general are case-sensitive (with the exception of machine names).
There may be URLs, or parts of URLs, where case doesn&rsquo;t matter, but
identifying these may not be easy. Users should always consider that URLs are
case-sensitive.</p></blockquote>

<p><em>In general</em> and <em>should</em> are the operative words there.  It&rsquo;s OK either way<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>, but assuming case-sensitivity is prudent.</p>

<h2>So What About Slim?</h2>

<p>URLs in the Slim Framework are case-sensitive<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>.  That&rsquo;s correct based on
what we learned about URL case-sensitivity from the w3c, but what if you have a
use case that requires case-insensitive URLs? What do do then?</p>

<h2>The Magic of Slim Hooks</h2>

<p>What are Slim Hooks?  From the <a href="http://docs.slimframework.com/#Hooks-Overview">documentation</a>:</p>

<blockquote><p>A “hook” is a moment in the Slim application lifecycle at which a priority
list of callables assigned to the hook will be invoked. A hook is identified
by a string name.</p></blockquote>

<p>Slim provides <a href="http://docs.slimframework.com/#Default-Hooks">six default hooks</a>,
three invoked before the current route is dispatched and three invoked after.
By using one of the hooks that&rsquo;s invoked before the route is matched, we can
alter the incoming URL&rsquo;s path to match the case of the routes we&rsquo;ve defined
in our Slim application.</p>

<h2>The Case-insensitive Route Hook</h2>

<p>First, if there are any routes with mixed case, <em>change them all to lower case</em>.
That&rsquo;s the de facto standard for creating routes anyhow, and if any requests
come in that match the old, mixed case routes, we&rsquo;ll take care of those with
the hook in the below example.  Same issue, we&rsquo;re just flipping it on its head.
Seriously, don&rsquo;t get weird about changing those routes.</p>

<p>Next, register this callback on the <code>slim.before.router</code> hook:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nv">$app</span><span class="o">-&gt;</span><span class="na">hook</span><span class="p">(</span><span class="s1">&#39;slim.before.router&#39;</span><span class="p">,</span> <span class="k">function</span> <span class="p">()</span> <span class="k">use</span> <span class="p">(</span><span class="nv">$app</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nv">$app</span><span class="o">-&gt;</span><span class="na">environment</span><span class="p">[</span><span class="s1">&#39;PATH_INFO&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nx">strtolower</span><span class="p">(</span><span class="nv">$app</span><span class="o">-&gt;</span><span class="na">environment</span><span class="p">[</span><span class="s1">&#39;PATH_INFO&#39;</span><span class="p">]);</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<p>This works because Slim matches the routes you&rsquo;ve defined against the Slim
Environment&rsquo;s <code>PATH_INFO</code> (originally found in <code>$_SERVER['PATH_INFO']</code>).  Since
your routes are lower case and the incoming request paths are lower case,
you&rsquo;ve accomplished case insensitive routing in 3 lines of code.  BOOM.</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>It&rsquo;s interesting to note that <a href="http://tools.ietf.org/html/rfc4343">domain names <em>are</em> case-insensitive</a>, regardless of whether or not that site&rsquo;s URLs are case-insensitive.<a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
<li id="fn:2">
<p>A pull request against Slim 2.4 is in the works that will allow case-insensitive routes via a config setting.<a href="#fnref:2" rev="footnote">&#8617;</a></p></li>
</ol>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using Callbacks to Bypass Guzzle's Cache Plugin]]></title>
    <link href="https://jeremykendall.net/2013/12/08/using-callbacks-to-bypass-guzzles-cache-plugin/"/>
    <updated>2013-12-08T14:43:48-06:00</updated>
    <id>https://jeremykendall.net/2013/12/08/using-callbacks-to-bypass-guzzles-cache-plugin</id>
    <content type="html"><![CDATA[<p>I&rsquo;m a big fan of the <a href="http://docs.guzzlephp.org/">Guzzle PHP HTTP client</a>.
I use it whenever I need to make requests of 3rd party APIs from my applications.
If you&rsquo;re still writing cURL requests by hand or have rolled your own HTTP
client, I highly recommend checking out Guzzle.</p>

<p>I&rsquo;m currently making heaviest use of Guzzle in my photo-a-day project,
<a href="https://github.com/jeremykendall/flaming-arche://github.com/jeremykendall/flaming-archer">Flaming Archer</a>,
in order to get photo data from Flickr. To keep from hammering the
<a href="http://www.flickr.com/services/api/">Flickr API</a>, I&rsquo;m caching all of those
requests. Guzzle makes caching ridiculously easy by way of their plugin system
and their <a href="http://docs.guzzlephp.org/en/latest/plugins/cache-plugin.html">HTTP Cache plugin</a>.</p>

<p>The problem with the caching plugin, at least at first blush, is how to bypass
the cache in certain specific instances where caching might not be appropriate.
The <a href="http://docs.guzzlephp.org/en/latest/plugins/cache-plugin.html#custom-caching-decision">docs are a little light in this area</a>,
so it took me a few minutes to get it sorted out. Let&rsquo;s start at the top.</p>

<h3>The Guzzle Client</h3>

<blockquote><p>&ldquo;Clients create requests, send requests, and set responses on a request
object. When instantiating a client object, you can pass an optional "base
URL&rdquo; and optional array of configuration options."</p></blockquote>

<p>Here&rsquo;s an example of creating a Guzzle Client, based on my use case of making
requests against the Flickr API.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">use</span> <span class="nx">Guzzle\Http\Client</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$client</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Client</span><span class="p">(</span><span class="s1">&#39;http://api.flickr.com&#39;</span><span class="p">);</span>
</span><span class='line'><span class="nv">$client</span><span class="o">-&gt;</span><span class="na">setDefaultOption</span><span class="p">(</span><span class="s1">&#39;query&#39;</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span>
</span><span class='line'>    <span class="s1">&#39;api_key&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;EXAMPLE_API_KEY&#39;</span><span class="p">,</span>
</span><span class='line'>    <span class="s1">&#39;format&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;json&#39;</span><span class="p">,</span>
</span><span class='line'>    <span class="s1">&#39;nojsoncallback&#39;</span> <span class="o">=&gt;</span> <span class="mi">1</span><span class="p">,</span>
</span><span class='line'><span class="p">));</span>
</span></code></pre></td></tr></table></div></figure>


<p>I use the client for the <code>GET</code> requests I need to make against the Flickr API.  Each request will include
the above default options in the query string.  Nice!</p>

<h3>Adding Caching</h3>

<p>Since I don&rsquo;t want to hammer the crap out of the Flickr API and start hitting
the rate limit<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>, I wanted to cache each request. Thankfully, Guzzle has an
awesome plugin system that includes an
<a href="http://docs.guzzlephp.org/en/latest/plugins/cache-plugin.html">HTTP Cache plugin</a>.</p>

<blockquote><p>&ldquo;Guzzle can leverage HTTP&rsquo;s caching specifications using the
Guzzle\Plugin\Cache\CachePlugin. The CachePlugin provides a private
transparent proxy cache that caches HTTP responses.&rdquo;</p></blockquote>

<p>Rather than rolling my own caching strategy (My first solution was to write a
<a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator</a> for caching),
I decided to use Guzzle&rsquo;s native plugin and leave all the caching work to them.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="k">use</span> <span class="nx">Guzzle\Cache\Zf2CacheAdapter</span><span class="p">;</span>
</span><span class='line'><span class="k">use</span> <span class="nx">Guzzle\Plugin\Cache\CachePlugin</span><span class="p">;</span>
</span><span class='line'><span class="k">use</span> <span class="nx">Guzzle\Plugin\Cache\DefaultCacheStorage</span><span class="p">;</span>
</span><span class='line'><span class="k">use</span> <span class="nx">Zend\Cache\Backend\TestBackend</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$backend</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">TestBackend</span><span class="p">();</span>
</span><span class='line'><span class="nv">$adapter</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Zf2CacheAdapter</span><span class="p">(</span><span class="nv">$backend</span><span class="p">);</span>
</span><span class='line'><span class="nv">$storage</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">DefaultCacheStorage</span><span class="p">(</span><span class="nv">$adapter</span><span class="p">);</span>
</span><span class='line'><span class="nv">$cachePlugin</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">CachePlugin</span><span class="p">(</span><span class="nv">$storage</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$client</span><span class="o">-&gt;</span><span class="na">addSubscriber</span><span class="p">(</span><span class="nv">$cachePlugin</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>The cache plugin will now intercept and cache <code>GET</code> and <code>HEAD</code> requests made by the
client.</p>

<h3>Custom Caching Decisions</h3>

<p>So what if, now that you&rsquo;re caching each <code>GET</code> request, there&rsquo;s a request or
requests you don&rsquo;t want cached? Guzzle makes solving that problem trivial by
allowing for &ldquo;<a href="http://docs.guzzlephp.org/en/latest/plugins/cache-plugin.html#custom-caching-decision">custom caching decisions</a>&rdquo;,
but the documentation on how to make those custom decisions is decidedly light.</p>

<blockquote><p>&ldquo;&hellip; you can set a custom can_cache object on the constructor of the
CachePlugin and provide a Guzzle\Plugin\Cache\CanCacheInterface object. You
can use the Guzzle\Plugin\Cache\CallbackCanCacheStrategy to easily make a
caching decision based on an HTTP request and response.&rdquo;</p></blockquote>

<p>Wat?</p>

<p>That was clear as mud to me, so I spent a few minutes digging through the
source. This is what I came up with:</p>

<ul>
<li>The <code>CallbackCanCacheStrategy</code> provides a
method of providing callbacks to the cache plugin that, based on a boolean
response, determine whether or not a particular request or response should be
cached.</li>
<li>The <code>CallbackCanCacheStrategy</code> accepts two optional arguments to its
constructor: a callable that will be invoked for requests and a callable that
will be invoked for responses.  The request callback gets an instance of
<code>Guzzle\Http\Message\RequestInterface</code>, and the response callback gets an
instance of <code>Guzzle\Http\Message\Response</code>.</li>
</ul>


<h3>Bypassing Cache</h3>

<p>In my case, I want to cache everything except for calls to the
<a href="http://www.flickr.com/services/api/flickr.photos.search.html">flickr.photos.search</a>
API method. Since all of the <code>GET</code> requests I&rsquo;m making include a <code>method</code> query string param,
it was trivial to write the callback that got me where I needed to go.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nv">$canCache</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">CallbackCanCacheStrategy</span><span class="p">(</span>
</span><span class='line'>    <span class="k">function</span> <span class="p">(</span><span class="nv">$request</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$request</span><span class="o">-&gt;</span><span class="na">getQuery</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">get</span><span class="p">(</span><span class="s1">&#39;method&#39;</span><span class="p">)</span> <span class="o">===</span> <span class="s1">&#39;flickr.photos.search&#39;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="k">return</span> <span class="k">false</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Putting It All Together</h3>

<p>Now that I&rsquo;ve built my <code>$client</code>, <code>$storage</code>, and <code>$canCache</code> strategy, here&rsquo;s
how I put it all together.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nv">$cachePlugin</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">CachePlugin</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
</span><span class='line'>    <span class="s1">&#39;can_cache&#39;</span> <span class="o">=&gt;</span> <span class="nv">$canCache</span><span class="p">,</span>
</span><span class='line'>    <span class="s1">&#39;storage&#39;</span> <span class="o">=&gt;</span> <span class="nv">$storage</span><span class="p">,</span>
</span><span class='line'><span class="p">));</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$client</span><span class="o">-&gt;</span><span class="na">addSubscriber</span><span class="p">(</span><span class="nv">$cachePlugin</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now all of my <code>GET</code> requests are cached <em>except</em> for those using the <code>flickr.photos.search</code> method. BOOM.</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>I can&rsquo;t find the documentation on API rate limiting right now, but I know it&rsquo;s limited and I don&rsquo;t want to hit that limit.<a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
</ol>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[PHP and Capistrano 3: Notes to Self]]></title>
    <link href="https://jeremykendall.net/2013/11/24/php-and-capistrano-3-notes-to-self/"/>
    <updated>2013-11-24T07:43:00-06:00</updated>
    <id>https://jeremykendall.net/2013/11/24/php-and-capistrano-3-notes-to-self</id>
    <content type="html"><![CDATA[<p>I spent quite a bit of my day yesterday trying to work out a painless,
scripted, idiot-proof deployment process with <a href="http://www.capistranorb.com/">Capistrano</a> for my
<a href="http://365.jeremykendall.net/">photo-a-day website</a>.  I&rsquo;ve been doing a lot of work on the
site lately, which means a lot of deployments, and I&rsquo;ve been very unhappy with
myself for implementing what amounts to &ldquo;deployment worst practices&rdquo; when it
comes to my personal projects.</p>

<p>The last time I worked with Capistrano was about two years ago, and a lot has changed
since then.  Capistrano v3 <a href="http://www.capistranorb.com/2013/06/01/release-announcement.html">was released in June of 2013</a>
and brought with it a lot of great changes, but for a guy who doesn&rsquo;t know ruby and
relies on tutorials and Stack Overflow questions for help, the version bump brought
a lot of pain as well.</p>

<h2>Challenges</h2>

<h3>Every Tutorial is Wrong</h3>

<p>Just know going into this that (almost) <a href="https://www.google.com/search?q=php+capistrano+v3&amp;oq=php+capistrano+v3&amp;aqs=chrome..69i57j69i64.3471j0j7&amp;sourceid=chrome&amp;espv=210&amp;es_sm=91&amp;ie=UTF-8">every tutorial you find</a>
is going to be a Capistrano v2 tutorial.  Enough has changed between v2 and v3
to make those tutorials just misleading enough to cause a good amount of pain.</p>

<h3>Stack Overflow is a Capistrano v3 Desert</h3>

<p>As of this writing, there are <a href="http://stackoverflow.com/questions/tagged/capistrano3">ten questions tagged capistrano3</a>
on Stack Overflow. Seriously. Ten. And only four of those include accepted answers.</p>

<h3>Capistrano v3 Documentation is Lacking</h3>

<p>The documentation available for v3 is seriously lacking, although the problem
is more one of quantity than quality. <a href="http://www.capistranorb.com/">What&rsquo;s available is good</a>,
there&rsquo;s just nowhere near enough of it.</p>

<h3>Caveat Emptor</h3>

<p>These are indeed &ldquo;Notes to Self&rdquo;.  I hope they help you out, but if they don&rsquo;t,
I&rsquo;m giving you fair warning.  Please feel free to add what&rsquo;s missing to the
comments.</p>

<p><em>Reading the </em><a href="http://www.capistranorb.com/">Capistrano</a> <em>docs is highly
recommended. These notes are supplemental.</em></p>

<h2>PHP + Capistrano v3</h2>

<p><em>NOTE: You can find the application source, which now includes Capistrano v3,
<a href="https://github.com/jeremykendall/flaming-archer">on GitHub</a>.</em></p>

<h3>Ruby</h3>

<p>First, I had to reinstall <a href="https://rvm.io/rvm/install">rvm</a>, a ruby version manager.
What I don&rsquo;t know about installing a ruby dev environment could fill books, so I let
rvm take care of that for me.</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>\curl -L https://get.rvm.io | bash -s stable --ruby</span></code></pre></td></tr></table></div></figure>


<p>(Capistrano <strong>requires Ruby 1.9 or newer</strong>, so the current stable Ruby from rvm
will work fine.)</p>

<h3>Installation</h3>

<p><a href="http://www.capistranorb.com/documentation/getting-started/installation/">Install Capistrano</a>.
There are a few options, but I used <code>gem install</code>.</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>gem install capistrano</span></code></pre></td></tr></table></div></figure>


<p><strong>NOTE</strong>: All of the PHP tutorials I found instruct you to install the
<code>railsless-deploy</code> gem. As Capistrano v3 &ldquo;doesn&rsquo;t ship with any Railsisms&rdquo;,
this is no longer necessary and the <a href="https://github.com/leehambley/railsless-deploy">railsless-deploy project is obsolete</a>.</p>

<p><em>I&rsquo;ll probably go back and add a</em> <code>Gemfile</code> <em>since I&rsquo;ll be adding the composer gem and want everything I need in one place.</em></p>

<h3>Preparing Your App</h3>

<p>The <code>capify</code> command is no longer, it&rsquo;s now <code>cap install</code>.</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>cd /path/to/project
</span><span class='line'>cap install</span></code></pre></td></tr></table></div></figure>


<p>The documentation on this portion, <a href="http://www.capistranorb.com/documentation/getting-started/preparing-your-application/">&ldquo;Preparing Your Application&rdquo;</a>,
is one of the places the documentation shines, IMHO.</p>

<h3>Capistrano Files</h3>

<ul>
<li><code>Capfile</code>: Kind of like a bootstrap. Takes care of necessary required
configs and globs for custom tasks.</li>
<li><code>config/deploy.rb</code>: Common items across all deployments go here</li>
<li><code>config/deploy/{staging, production}.rb</code>: Environment specific deployment settings</li>
</ul>


<h3>Roles</h3>

<p>I&rsquo;m still not 100% clear on this, but roles don&rsquo;t seem to be roles in the ACL
sense, but rather roles in the &ldquo;division of server responsibility&rdquo; sense, hence the
roles <code>:web</code>, <code>:app</code>, and <code>:db</code>.</p>

<p><a href="http://www.capistranorb.com/documentation/getting-started/preparing-your-application/#toc_3">The docs say</a> that you can dump the <code>:app</code> and <code>:db</code> roles if you like, but if
you&rsquo;re going to use the <code>:linked_files</code> and <code>:linked_dirs</code> feature (which are
pretty cool) you&rsquo;ll need to leave the <code>:app</code> role in place. I&rsquo;m obviously doing
something wrong or missing something here, but that&rsquo;s what I had to do.</p>

<p>I found it extremely helpful to refer to the <a href="https://github.com/capistrano/capistrano/blob/master/lib/capistrano/templates/deploy.rb.erb"><code>deploy.rb.erb</code> template</a>.
I removed most of the example text before realizing I needed to use some of it,
and referencing the template was nice.</p>

<h3>SSH Forwarding</h3>

<p>SSH Agent Forwarding is the way to go here, IMHO.  I already had a key agent running
so the <a href="http://www.capistranorb.com/documentation/getting-started/authentication-and-authorisation/#toc_3">forwarding was dead simple</a>,
almost like magic.  If you don&rsquo;t already have an agent running,
<a href="https://help.github.com/articles/working-with-ssh-key-passphrases">here&rsquo;s some good info</a>
from GitHub Help.</p>

<h3>Server Config</h3>

<p>The section on how to set up the proper Capistrano directories on your server is
<a href="http://www.capistranorb.com/documentation/getting-started/authentication-and-authorisation/#toc_8">way down deep in the Authorisation portion of the docs</a>.
Short version: you need two dirs in the root of your project (on the server):
<code>releases</code> and <code>shared</code>, and they must be readable and writeable by both the
webserver and deploy user.</p>

<p><em>Getting permissions right is easy for some, but I always return to the</em>
<a href="http://symfony.com/doc/current/book/installation.html#configuration-and-setup">Setting Up Permissions</a>
<em>section of the Symfony2 docs to get them set up properly.</em></p>

<h3>Making Composer Work</h3>

<p>Once I got my <code>deploy.rb</code> and <code>deploy/production.rb</code> right and tested (by deploying, natch),
I needed to create a task to run <a href="http://getcomposer.org"><code>composer install</code></a>.
Getting that right turned out to be pretty difficult because of a design decision
in SSHKit.</p>

<p>Short story: <a href="https://github.com/capistrano/capistrano/issues/719#issuecomment-26917090">No spaces in command line commands</a>.</p>

<p>I finally got my composer command running <a href="https://github.com/jeremykendall/flaming-archer/blob/dc1900aab5386b164430b001032b310f78a3c0e5/config/deploy.rb#L18-L27">by doing this</a>:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>desc 'composer install'
</span><span class='line'>task :composer_install do
</span><span class='line'>    on roles(:web) do
</span><span class='line'>        within release_path do
</span><span class='line'>            execute 'composer', 'install', '--no-dev', '--optimize-autoloader'
</span><span class='line'>        end
</span><span class='line'>    end
</span><span class='line'>end
</span><span class='line'>
</span><span class='line'>after :updated, 'deploy:composer_install'</span></code></pre></td></tr></table></div></figure>


<ul>
<li>The <code>within release</code> bit in the command tells the task to <code>cd</code> into the
<code>release</code> directory before running composer.</li>
<li>There are <code>before</code> and <code>after</code> hooks you can apply to the deploy flow. The final line above is a hook that runs after <code>deploy:updated</code>.</li>
</ul>


<h3>Composer Gem for Capistrano v3</h3>

<p>Of course, as soon as I got it working, Peter Mitchell sent me this tweet:</p>

<div class='embed twitter'><blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/JeremyKendall">@JeremyKendall</a> Don’t bother, just install this gem (or check out the code) <a href="http://t.co/DitSaKlsqb">http://t.co/DitSaKlsqb</a></p>&mdash; Peter Mitchell (@Peterjmit) <a href="https://twitter.com/Peterjmit/status/404324240339771392">November 23, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></div>


<p>I haven&rsquo;t yet replaced my hacked version with the gem, but I&rsquo;ll use it
as soon as I do any refactoring.</p>

<h3>Deployment Annoyances</h3>

<p><code>cap production deploy --dry-run</code> never worked for me, although <code>cap production deploy</code>
worked fine.  No idea why, who cares at this point.  Maybe I&rsquo;ll dig in later.</p>

<p>Also, <code>cap production deploy</code> <em>really</em> wants to run <code>deploy:restart</code>, even
though it doesn&rsquo;t show up anywhere in the <a href="http://www.capistranorb.com/documentation/getting-started/flow/">deploy flow</a>.
I replaced the <code>:restart</code> task that&rsquo;s in the default <code>deploy.rb</code> template, made
sure it was empty, and deploy finally worked.</p>

<h3>Linked Files and Directories</h3>

<p>The <code>:linked_files</code> and <code>:linked_directories</code> feature is really nice. I&rsquo;ve used
it for logs, a <code>local.php</code> config, Twig caching, my SQLite database, and my
generated rss file. The linked items are for files and dirs that should be
shared between deploys.</p>

<p>Also, those files and dirs need to be present in the shared dir before
deploying. Deploy will puke if they&rsquo;re not present.</p>

<h3>Capistrano Variables</h3>

<p>I couldn&rsquo;t find a listing of these anywhere, but <code>release_path</code> is one of them,
and it points to the latest release path.</p>

<h2>That&rsquo;s All For Now</h2>

<p>I hope the notes help when you get ready to write your own Capistrano v3 scripts
for use with PHP.  I&rsquo;ll update this as I learn more, and I&rsquo;ll make sure to point out
any excellent point made in the comments.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Restarting VirtualBox on OSX]]></title>
    <link href="https://jeremykendall.net/2013/08/19/restarting-virtualbox-on-osx/"/>
    <updated>2013-08-19T17:51:00-05:00</updated>
    <id>https://jeremykendall.net/2013/08/19/restarting-virtualbox-on-osx</id>
    <content type="html"><![CDATA[<p>My Vagrant + VirtualBox VM workflow was distrupted late this afternoon by
an error during <code>vagrant up</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>vagrant up
</span><span class='line'>Bringing machine <span class="s1">&#39;default&#39;</span> up with <span class="s1">&#39;virtualbox&#39;</span> provider...
</span><span class='line'><span class="o">[</span>default<span class="o">]</span> Importing base box <span class="s1">&#39;precise64&#39;</span>...
</span><span class='line'><span class="o">[</span>default<span class="o">]</span> Matching MAC address <span class="k">for </span>NAT networking...
</span><span class='line'><span class="o">[</span>default<span class="o">]</span> Setting the name of the VM...
</span><span class='line'><span class="o">[</span>default<span class="o">]</span> Clearing any previously <span class="nb">set </span>forwarded ports...
</span><span class='line'><span class="o">[</span>default<span class="o">]</span> Creating shared folders metadata...
</span><span class='line'><span class="o">[</span>default<span class="o">]</span> Clearing any previously <span class="nb">set </span>network interfaces...
</span><span class='line'>There was an error <span class="k">while </span>executing <span class="sb">`</span>VBoxManage<span class="sb">`</span>, a CLI used by Vagrant
</span><span class='line'><span class="k">for </span>controlling VirtualBox. The <span class="nb">command </span>and stderr is shown below.
</span><span class='line'>
</span><span class='line'>    Command: <span class="o">[</span><span class="s2">&quot;hostonlyif&quot;</span>, <span class="s2">&quot;create&quot;</span><span class="o">]</span>
</span><span class='line'>
</span><span class='line'>    Stderr: 0%...
</span><span class='line'>    Progress state: NS_ERROR_FAILURE
</span><span class='line'>    VBoxManage: error: Failed to create the host-only adapter
</span><span class='line'>    VBoxManage: error: VBoxNetAdpCtl: Error <span class="k">while </span>adding new interface: failed to open /dev/vboxnetctl: No such file or directory
</span><span class='line'>
</span><span class='line'>    VBoxManage: error: Details: code NS_ERROR_FAILURE <span class="o">(</span>0x80004005<span class="o">)</span>, component HostNetworkInterface, interface IHostNetworkInterface
</span><span class='line'>    VBoxManage: error: Context: <span class="s2">&quot;int handleCreate(HandlerArg*, int, int*)&quot;</span> at line 68 of file VBoxManageHostonly.cpp
</span></code></pre></td></tr></table></div></figure>


<p>Googling for <code>Failed to create the host-only adapter</code> didn&rsquo;t seem to return anything
useful, so I tried with <code>failed to open /dev/vboxnetctl</code> and immediately found an answer.</p>

<p>The trick, according to GitHub user <a href="https://github.com/lslucas">lslucas</a>, is to
<a href="https://github.com/mitchellh/vagrant/issues/1671#issuecomment-22146167">restart VirtualBox from the command line</a>
like so:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'> <span class="nv">$ </span>sudo /Library/StartupItems/VirtualBox/VirtualBox restart
</span></code></pre></td></tr></table></div></figure>


<p>That worked like a champ for me, and I was immediately able to get back to work.</p>

<p>For what it&rsquo;s worth, here&rsquo;s my current software config:</p>

<ul>
<li>VirtualBox 4.2.16</li>
<li>Vagrant 1.2.2</li>
<li>Mac OS X 10.8.4</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Nashville, I Hardly Knew Ye]]></title>
    <link href="https://jeremykendall.net/2013/08/16/nashville-i-hardly-knew-ye/"/>
    <updated>2013-08-16T15:01:00-05:00</updated>
    <id>https://jeremykendall.net/2013/08/16/nashville-i-hardly-knew-ye</id>
    <content type="html"><![CDATA[<h3>tl;dr:</h3>

<ul>
<li>My wife Megan and I are moving back to Memphis, TN</li>
<li>All of our family is there</li>
<li>The pregnancy has been tough, we&rsquo;d like to raise our son around family</li>
<li>I&rsquo;m leaving Nashville, but I&rsquo;ll still be working for <a href="http://www.opensky.com">OpenSky</a></li>
<li>I&rsquo;ll miss you all terribly, but I&rsquo;ll be back regularly</li>
</ul>


<h2>So Long, And Thanks For All The Awesome</h2>

<p>I might as well get right to it, especially since I ruined the surprise above:
Megan and I have decided to move back to Memphis. The decision to leave Nashville,
especially after spending such a short time here, was a really difficult one, but
I&rsquo;m convinced this is the best decision for me and my family.</p>

<h2>A Little Background</h2>

<p>Megan and I are both Memphis natives.  We&rsquo;ve got deep roots in the &ldquo;Bluff City&rdquo;,
and both of our families (excepting one of my brothers and his family) are still
there. We moved to Nashville late last year after the incomparable <a href="https://twitter.com/sgordon70">Scott Gordon</a>
hooked me up with an awesome gig here in town.</p>

<p>In April of this year <a href="http://baby.biggskendall.com/post/were-having-a-baby">we found out we&rsquo;d be having a baby</a>!
That was amazing, wonderful news, but the pregnancy has been difficult from day one.
Recently, things got <a href="http://baby.biggskendall.com/post/of-cervical-incompetence-terror-and-hope">really, really scary</a>.
After a lot of discussion and soul searching, Megan and I decided the best decision
for us and our new family would be moving home to be around the support, care,
and help of our families.</p>

<h2>I&rsquo;m Leaving, But Only Mostly</h2>

<p>So come mid- to late-October, when our current lease is up, we&rsquo;re heading back
to M-town.  There is a <em>huge</em> Nashville-related silver lining, however.  <a href="http://www.opensky.com">OpenSky</a>
is letting me move to Memphis while staying on staff with them!  That means
regular trips back to Nashville to work in the local office, get some face time
with the team, and hang out with all my Nashville friends.</p>

<h2>So Let&rsquo;s Do Lunch</h2>

<p>Nashville friends, we need to do lunch, pronto.  Two months seems like a long time,
but I&rsquo;ll be driving that moving truck west on I-40 before we know it.  I want to get together
while it&rsquo;s still relatively easy to do so.  I&rsquo;ve spent to little time with y'all
as it is.</p>

<h2>MEMPHIS, I AM ALMOST BACK IN YOU</h2>

<p>Leaving Nashville is sad, coming back to Memphis is going to be awesome.  I&rsquo;m
looking forward to hanging out with my Memphis people, getting involved in the
<a href="http://memphisphp.org">Memphis PHP</a> and the <a href="https://twitter.com/search?q=%23memtech&amp;src=typd">#memtech</a>
communities again, reconnecting with <a href="http://www.memphisrollerderby.com/">Memphis Roller Derby</a>,
and being able to see the fam whenever.</p>

<h2>Exciting Times Ahead</h2>

<p>Things have been wild the past few years, and they&rsquo;re about to get a lot
more exciting.  Change is tough, and I&rsquo;m feeling the pressure, but I feel
great about where I&rsquo;m at, where Megan and I are at, and our future.  I can&rsquo;t wait
to see what comes next.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Trending on GitHub]]></title>
    <link href="https://jeremykendall.net/2013/08/16/trending-on-github/"/>
    <updated>2013-08-16T07:04:00-05:00</updated>
    <id>https://jeremykendall.net/2013/08/16/trending-on-github</id>
    <content type="html"><![CDATA[<div class='embed twitter'><blockquote class="twitter-tweet"><p lang="en" dir="ltr">As of 06:58 CDT, I&#39;m on the trending dev and trending repo lists on GitHub. Two thumbs, internet famous, this guy. <a href="https://t.co/stWaUkV34e">https://t.co/stWaUkV34e</a></p>&mdash; Jeremy Kendall (@JeremyKendall) <a href="https://twitter.com/JeremyKendall/status/368341245695115264">August 16, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></div>


<p>Thanks to yesterday&rsquo;s link love from <a href="http://phpdeveloper.org/news/19985">PHPDeveloper</a>,
I&rsquo;ve made both the <a href="https://github.com/trending/developers?l=php">Trending PHP Developer</a>
list and the <a href="https://github.com/trending?l=php">Trending PHP Repo</a> list on GitHub.</p>

<p>With internet fame being so fleeting, I took some screenshots for posterity.  Now please
excuse me while I get some ice for my arm. I seem to have injured myself while patting
myself on the back.</p>

<p><img src="http://farm4.staticflickr.com/3707/9521081913_165b923775_z.jpg"></p>

<p><img src="http://farm4.staticflickr.com/3767/9523868202_b9ee2c6355_z.jpg"></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[API Query Authentication With Query Auth]]></title>
    <link href="https://jeremykendall.net/2013/08/13/api-query-authentication-with-query-auth/"/>
    <updated>2013-08-13T12:57:00-05:00</updated>
    <id>https://jeremykendall.net/2013/08/13/api-query-authentication-with-query-auth</id>
    <content type="html"><![CDATA[<p>Most APIs require some sort of query authentication: a method of signing API
requests with an API key and signature.  The signature is usually generated
using a shared secret.  When you&rsquo;re consuming an API, there are (hopefully) easy
to follow steps to create signatures. When you&rsquo;re writing your own API, you
have to whip up both server-side signature validation and a client-side
signature creation strategy. <a href="https://github.com/jeremykendall/query-auth">Query Auth</a>
endeavors to handle both of those tasks; signature creation and signature validation.</p>

<h2>Philosophy</h2>

<p>Query Auth is intended to be &ndash; and is written as &ndash; a bare bones library.  Many of
niceties and abstractions you&rsquo;d find in a fully featured API library or SDK are
absent.  The point of the library is to provide you with the ability to
focus on writing the meat of your API while offloading the authentication bits.</p>

<h2>What&rsquo;s Included?</h2>

<p>There are three components to Query Auth: request signing for API consumers
and creators, request signature validation for API creators, and API key and
API secret generation.</p>

<h3>Request Signing</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nv">$collection</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">QueryAuth\NormalizedParameterCollection</span><span class="p">();</span>
</span><span class='line'><span class="nv">$signer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">QueryAuth\Signer</span><span class="p">(</span><span class="nv">$collection</span><span class="p">);</span>
</span><span class='line'><span class="nv">$client</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">QueryAuth\Client</span><span class="p">(</span><span class="nv">$signer</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$key</span> <span class="o">=</span> <span class="s1">&#39;API_KEY&#39;</span><span class="p">;</span>
</span><span class='line'><span class="nv">$secret</span> <span class="o">=</span> <span class="s1">&#39;API_SECRET&#39;</span><span class="p">;</span>
</span><span class='line'><span class="nv">$method</span> <span class="o">=</span> <span class="s1">&#39;GET&#39;</span><span class="p">;</span>
</span><span class='line'><span class="nv">$host</span> <span class="o">=</span> <span class="s1">&#39;api.example.com&#39;</span><span class="p">;</span>
</span><span class='line'><span class="nv">$path</span> <span class="o">=</span> <span class="s1">&#39;/resources&#39;</span><span class="p">;</span>
</span><span class='line'><span class="nv">$params</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;type&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;vehicles&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$signedParameters</span> <span class="o">=</span> <span class="nv">$client</span><span class="o">-&gt;</span><span class="na">getSignedRequestParams</span><span class="p">(</span><span class="nv">$key</span><span class="p">,</span> <span class="nv">$secret</span><span class="p">,</span> <span class="nv">$method</span><span class="p">,</span> <span class="nv">$host</span><span class="p">,</span> <span class="nv">$path</span><span class="p">,</span> <span class="nv">$params</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>Client::getSignedRequestParams()</code> returns an array of parameters to send via
the querystring (for <code>GET</code> requests) or the request body. The parameters are
those provided to the method (if any), plus <code>timestamp</code>, <code>key</code>, and <code>signature</code>.</p>

<h3>Signature Validation</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nv">$collection</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">QueryAuth\NormalizedParameterCollection</span><span class="p">();</span>
</span><span class='line'><span class="nv">$signer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">QueryAuth\Signer</span><span class="p">(</span><span class="nv">$collection</span><span class="p">);</span>
</span><span class='line'><span class="nv">$server</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">QueryAuth\Server</span><span class="p">(</span><span class="nv">$signer</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$secret</span> <span class="o">=</span> <span class="s1">&#39;API_SECRET_FROM_PERSISTENCE_LAYER&#39;</span><span class="p">;</span>
</span><span class='line'><span class="nv">$method</span> <span class="o">=</span> <span class="s1">&#39;GET&#39;</span><span class="p">;</span>
</span><span class='line'><span class="nv">$host</span> <span class="o">=</span> <span class="s1">&#39;api.example.com&#39;</span><span class="p">;</span>
</span><span class='line'><span class="nv">$path</span> <span class="o">=</span> <span class="s1">&#39;/resources&#39;</span><span class="p">;</span>
</span><span class='line'><span class="c1">// querystring params or request body as an array,</span>
</span><span class='line'><span class="c1">// which includes timestamp, key, and signature params from the client&#39;s</span>
</span><span class='line'><span class="c1">// getSignedRequestParams method</span>
</span><span class='line'><span class="nv">$params</span> <span class="o">=</span> <span class="s1">&#39;PARAMS_FROM_REQUEST&#39;</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="nv">$isValid</span> <span class="o">=</span> <span class="nv">$server</span><span class="o">-&gt;</span><span class="na">validateSignature</span><span class="p">(</span><span class="nv">$secret</span><span class="p">,</span> <span class="nv">$method</span><span class="p">,</span> <span class="nv">$host</span><span class="p">,</span> <span class="nv">$path</span><span class="p">,</span> <span class="nv">$params</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>Server::validateSignature()</code> will return either true or false.  It might also
throw one of three exceptions:</p>

<ul>
<li><code>MaximumDriftExceededException</code>: If timestamp is too far in the future</li>
<li><code>MinimumDriftExceededException</code>: It timestamp is too far in the past</li>
<li><code>SignatureMissingException</code>: If signature is missing from request params</li>
</ul>


<p>Drift defaults to 15 seconds, meaning there is a 30 second window during which the
request is valid. The default value can be modified using <code>Server::setDrift()</code>.</p>

<h3>Key Generation</h3>

<p>You can generate API keys and secrets in the following manner.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nv">$randomFactory</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">\RandomLib\Factory</span><span class="p">();</span>
</span><span class='line'><span class="nv">$keyGenerator</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">QueryAuth\KeyGenerator</span><span class="p">(</span><span class="nv">$randomFactory</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// 40 character random alphanumeric string</span>
</span><span class='line'><span class="nv">$key</span> <span class="o">=</span> <span class="nv">$keyGenerator</span><span class="o">-&gt;</span><span class="na">generateKey</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// 60 character random string containing the characters</span>
</span><span class='line'><span class="c1">// 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./</span>
</span><span class='line'><span class="nv">$secret</span> <span class="o">=</span> <span class="nv">$keyGenerator</span><span class="o">-&gt;</span><span class="na">generateSecret</span><span class="p">();</span>
</span></code></pre></td></tr></table></div></figure>


<p>Both key and secret are generated using Anthony Ferrara&rsquo;s <a href="https://github.com/ircmaxell/RandomLib">RandomLib</a>
random string generator.</p>

<h2>That&rsquo;s Kinda Ugly, Dude</h2>

<p>As I pointed out, the Query Auth library is pretty bare bones.  There are a lot
of opportunities for abstraction that would make the library much easier to use
and much nicer to look at.  If I added them to Query Auth, however, that
would lock library users into whichever HTTP client I chose to use. The same
concern would go for whatever other abstractions I decided on. The point here is
to offload query authentication, and only query authentication, to the Query Auth
library.</p>

<h2>Sample Implementation</h2>

<p>In order to demonstrate how one might implement the Query Auth library, I&rsquo;ve whipped
up a <a href="https://github.com/jeremykendall/query-auth-impl">sample implementation</a> for you.</p>

<p>The sample uses <a href="http://www.vagrantup.com/">Vagrant</a> and <a href="https://www.virtualbox.org/">VirtualBox</a>
to allow you to see the whole thing in action.  <a href="http://slimframework.com/">Slim Framework</a>
runs the API, <a href="http://guzzlephp.org/">Guzzle</a> is used to make requests to the API,
and both a <code>GET</code> and <code>POST</code> request are implemented.  <a href="https://github.com/shkm/JSend">JSend</a>,
<a href="https://twitter.com/shkm">Jamie Schembri&rsquo;s</a> PHP implementation of the
OmniTI <a href="http://labs.omniti.com/labs/jsend">JSend specifiction</a>, is used to send
messages back from the API, and <a href="https://github.com/erusev/parsedown">Parsedown PHP</a>,
Emanuil Rusev&rsquo;s Markdown parser for PHP, is used to render the sample implementation&rsquo;s
documentation.</p>

<h3>Request Signing</h3>

<p>In the sample implementation, request signing has been abstracted in the
<code>Example\ApiRequestSigner</code> class. Signing requests is now as simple as passing
the request object and credentials object to the <code>signRequest</code> method:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Signs API request</span>
</span><span class='line'><span class="sd"> *</span>
</span><span class='line'><span class="sd"> * @param RequestInterface $request     HTTP Request</span>
</span><span class='line'><span class="sd"> * @param ApiCredentials   $credentials API Credentials</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">public</span> <span class="k">function</span> <span class="nf">signRequest</span><span class="p">(</span><span class="nx">RequestInterface</span> <span class="nv">$request</span><span class="p">,</span> <span class="nx">ApiCredentials</span> <span class="nv">$credentials</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>    <span class="nv">$signedParams</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">client</span><span class="o">-&gt;</span><span class="na">getSignedRequestParams</span><span class="p">(</span>
</span><span class='line'>            <span class="nv">$credentials</span><span class="o">-&gt;</span><span class="na">getKey</span><span class="p">(),</span>
</span><span class='line'>            <span class="nv">$credentials</span><span class="o">-&gt;</span><span class="na">getSecret</span><span class="p">(),</span>
</span><span class='line'>            <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">getMethod</span><span class="p">(),</span>
</span><span class='line'>            <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">getHost</span><span class="p">(),</span>
</span><span class='line'>            <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">getPath</span><span class="p">(),</span>
</span><span class='line'>            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">getParams</span><span class="p">(</span><span class="nv">$request</span><span class="p">)</span>
</span><span class='line'>            <span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">replaceParams</span><span class="p">(</span><span class="nv">$request</span><span class="p">,</span> <span class="nv">$signedParams</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Signature Validation</h3>

<p>In the sample implementation, signature validation has been abstracted in the
<code>Example\ApiRequestValidator</code> class. Validating request signatures is now as
simple as passing the request object and credentials object to the <code>isValid</code>
method:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Validates an API request</span>
</span><span class='line'><span class="sd"> *</span>
</span><span class='line'><span class="sd"> * @param  Request        $request     HTTP Request</span>
</span><span class='line'><span class="sd"> * @param  ApiCredentials $credentials API Credentials</span>
</span><span class='line'><span class="sd"> * @return bool           True if valid, false if invalid</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="k">public</span> <span class="k">function</span> <span class="nf">isValid</span><span class="p">(</span><span class="nx">Request</span> <span class="nv">$request</span><span class="p">,</span> <span class="nx">ApiCredentials</span> <span class="nv">$credentials</span><span class="p">)</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>    <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">server</span><span class="o">-&gt;</span><span class="na">validateSignature</span><span class="p">(</span>
</span><span class='line'>        <span class="nv">$credentials</span><span class="o">-&gt;</span><span class="na">getSecret</span><span class="p">(),</span>
</span><span class='line'>        <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">getMethod</span><span class="p">(),</span>
</span><span class='line'>        <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">getHost</span><span class="p">(),</span>
</span><span class='line'>        <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">getPath</span><span class="p">(),</span>
</span><span class='line'>        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">getParams</span><span class="p">(</span><span class="nv">$request</span><span class="p">)</span>
</span><span class='line'>    <span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Signing a GET Request</h3>

<p>Signing a request is now extremely clean and simple.  Here&rsquo;s the <code>GET</code> example from
the sample implementation.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Sends a signed GET request which returns a famous mangled phrase</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="nv">$app</span><span class="o">-&gt;</span><span class="na">get</span><span class="p">(</span><span class="s1">&#39;/get-example&#39;</span><span class="p">,</span> <span class="k">function</span><span class="p">()</span> <span class="k">use</span> <span class="p">(</span><span class="nv">$app</span><span class="p">,</span> <span class="nv">$credentials</span><span class="p">,</span> <span class="nv">$requestSigner</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// Create request</span>
</span><span class='line'>    <span class="nv">$guzzle</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">GuzzleClient</span><span class="p">(</span><span class="s1">&#39;http://query-auth.dev&#39;</span><span class="p">);</span>
</span><span class='line'>    <span class="nv">$request</span> <span class="o">=</span> <span class="nv">$guzzle</span><span class="o">-&gt;</span><span class="na">get</span><span class="p">(</span><span class="s1">&#39;/api/get-example&#39;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// Sign request</span>
</span><span class='line'>    <span class="nv">$requestSigner</span><span class="o">-&gt;</span><span class="na">signRequest</span><span class="p">(</span><span class="nv">$request</span><span class="p">,</span> <span class="nv">$credentials</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="nv">$response</span> <span class="o">=</span> <span class="nv">$request</span><span class="o">-&gt;</span><span class="na">send</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>    <span class="nv">$app</span><span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="s1">&#39;get.html&#39;</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;request&#39;</span> <span class="o">=&gt;</span> <span class="p">(</span><span class="nx">string</span><span class="p">)</span> <span class="nv">$request</span><span class="p">,</span> <span class="s1">&#39;response&#39;</span> <span class="o">=&gt;</span> <span class="p">(</span><span class="nx">string</span><span class="p">)</span> <span class="nv">$response</span><span class="p">));</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Validating a GET Request</h3>

<p>Validating a <code>GET</code> request is equally clean and simple.  Note the <code>try/catch</code> that
handles possible exceptions from the validation class.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="sd">/**</span>
</span><span class='line'><span class="sd"> * Validates a signed GET request and, if the request is valid, returns a</span>
</span><span class='line'><span class="sd"> * famous mangled phrase</span>
</span><span class='line'><span class="sd"> */</span>
</span><span class='line'><span class="nv">$app</span><span class="o">-&gt;</span><span class="na">get</span><span class="p">(</span><span class="s1">&#39;/api/get-example&#39;</span><span class="p">,</span> <span class="k">function</span> <span class="p">()</span> <span class="k">use</span> <span class="p">(</span><span class="nv">$app</span><span class="p">,</span> <span class="nv">$credentials</span><span class="p">,</span> <span class="nv">$requestValidator</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">try</span> <span class="p">{</span>
</span><span class='line'>        <span class="c1">// Validate the request signature</span>
</span><span class='line'>        <span class="nv">$isValid</span> <span class="o">=</span> <span class="nv">$requestValidator</span><span class="o">-&gt;</span><span class="na">isValid</span><span class="p">(</span><span class="nv">$app</span><span class="o">-&gt;</span><span class="na">request</span><span class="p">(),</span> <span class="nv">$credentials</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="nv">$isValid</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$mistakes</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;necktie&#39;</span><span class="p">,</span> <span class="s1">&#39;neckturn&#39;</span><span class="p">,</span> <span class="s1">&#39;nickle&#39;</span><span class="p">,</span> <span class="s1">&#39;noodle&#39;</span><span class="p">);</span>
</span><span class='line'>            <span class="nv">$format</span> <span class="o">=</span> <span class="s1">&#39;Klaatu... barada... n... %s!&#39;</span><span class="p">;</span>
</span><span class='line'>            <span class="nv">$data</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;message&#39;</span> <span class="o">=&gt;</span> <span class="nb">sprintf</span><span class="p">(</span><span class="nv">$format</span><span class="p">,</span> <span class="nv">$mistakes</span><span class="p">[</span><span class="nb">array_rand</span><span class="p">(</span><span class="nv">$mistakes</span><span class="p">)]));</span>
</span><span class='line'>            <span class="nv">$jsend</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JSendResponse</span><span class="p">(</span><span class="s1">&#39;success&#39;</span><span class="p">,</span> <span class="nv">$data</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">$jsend</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JSendResponse</span><span class="p">(</span><span class="s1">&#39;fail&#39;</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;message&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;Invalid signature&#39;</span><span class="p">));</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">\Exception</span> <span class="nv">$e</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="nv">$jsend</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JSendResponse</span><span class="p">(</span><span class="s1">&#39;error&#39;</span><span class="p">,</span> <span class="k">array</span><span class="p">(),</span> <span class="nv">$e</span><span class="o">-&gt;</span><span class="na">getMessage</span><span class="p">());</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="nv">$response</span> <span class="o">=</span> <span class="nv">$app</span><span class="o">-&gt;</span><span class="na">response</span><span class="p">();</span>
</span><span class='line'>    <span class="nv">$response</span><span class="p">[</span><span class="s1">&#39;Content-Type&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;application/json&#39;</span><span class="p">;</span>
</span><span class='line'>    <span class="k">echo</span> <span class="nv">$jsend</span><span class="o">-&gt;</span><span class="na">encode</span><span class="p">();</span>
</span><span class='line'><span class="p">});</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Sample Request and Response</h3>

<p>The code above produces the below request and response:</p>

<h4>Request</h4>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nx">GET</span> <span class="o">/</span><span class="nx">api</span><span class="o">/</span><span class="nx">get</span><span class="o">-</span><span class="nx">example</span><span class="o">?</span><span class="nb">key</span><span class="o">=</span><span class="nx">ah5yEgQzjuFsC9nWsRI4Nar3ikOqWVPcD3OntHpg</span><span class="o">&amp;</span><span class="nx">timestamp</span><span class="o">=</span><span class="mi">1376416267</span><span class="o">&amp;</span><span class="nx">signature</span><span class="o">=</span><span class="mi">3</span><span class="nx">DqimkvigYBorGi8wHfil9lB8oCWhB</span><span class="o">%</span><span class="mi">2</span><span class="nx">BHYt6rVfE4zx4</span><span class="o">%</span><span class="mi">3</span><span class="nx">D</span> <span class="nx">HTTP</span><span class="o">/</span><span class="mf">1.1</span>
</span><span class='line'><span class="nx">Host</span><span class="o">:</span> <span class="nx">query</span><span class="o">-</span><span class="nx">auth</span><span class="o">.</span><span class="nx">dev</span>
</span><span class='line'><span class="nx">User</span><span class="o">-</span><span class="nx">Agent</span><span class="o">:</span> <span class="nx">Guzzle</span><span class="o">/</span><span class="mf">3.7</span><span class="o">.</span><span class="mi">2</span> <span class="nx">curl</span><span class="o">/</span><span class="mf">7.22</span><span class="o">.</span><span class="mi">0</span> <span class="nx">PHP</span><span class="o">/</span><span class="mf">5.5</span><span class="o">.</span><span class="mi">1</span><span class="o">-</span><span class="mi">2</span><span class="o">+</span><span class="nx">debphp</span><span class="o">.</span><span class="nx">org</span><span class="o">~</span><span class="nx">precise</span><span class="o">+</span><span class="mi">2</span>
</span></code></pre></td></tr></table></div></figure>


<h4>Response</h4>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='php'><span class='line'><span class="nx">HTTP</span><span class="o">/</span><span class="mf">1.1</span> <span class="mi">200</span> <span class="nx">OK</span>
</span><span class='line'><span class="nx">Date</span><span class="o">:</span> <span class="nx">Tue</span><span class="p">,</span> <span class="mi">13</span> <span class="nx">Aug</span> <span class="mi">2013</span> <span class="mi">17</span><span class="o">:</span><span class="mi">51</span><span class="o">:</span><span class="mo">07</span> <span class="nx">GMT</span>
</span><span class='line'><span class="nx">Server</span><span class="o">:</span> <span class="nx">Apache</span><span class="o">/</span><span class="mf">2.4</span><span class="o">.</span><span class="mi">6</span> <span class="p">(</span><span class="nx">Ubuntu</span><span class="p">)</span>
</span><span class='line'><span class="nx">X</span><span class="o">-</span><span class="nx">Powered</span><span class="o">-</span><span class="nx">By</span><span class="o">:</span> <span class="nx">PHP</span><span class="o">/</span><span class="mf">5.5</span><span class="o">.</span><span class="mi">1</span><span class="o">-</span><span class="mi">2</span><span class="o">+</span><span class="nx">debphp</span><span class="o">.</span><span class="nx">org</span><span class="o">~</span><span class="nx">precise</span><span class="o">+</span><span class="mi">2</span>
</span><span class='line'><span class="nx">Content</span><span class="o">-</span><span class="nx">Length</span><span class="o">:</span> <span class="mi">75</span>
</span><span class='line'><span class="nx">Content</span><span class="o">-</span><span class="nx">Type</span><span class="o">:</span> <span class="nx">application</span><span class="o">/</span><span class="nx">json</span>
</span><span class='line'>
</span><span class='line'><span class="p">{</span><span class="s2">&quot;status&quot;</span><span class="o">:</span><span class="s2">&quot;success&quot;</span><span class="p">,</span><span class="s2">&quot;data&quot;</span><span class="o">:</span><span class="p">{</span><span class="s2">&quot;message&quot;</span><span class="o">:</span><span class="s2">&quot;Klaatu... barada... n... necktie!&quot;</span><span class="p">}}</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Wrapping Up</h2>

<p>So there you have it: <a href="https://github.com/jeremykendall/query-auth">QueryAuth</a>
to sign and validate API requests (and generate keys and secrets!) and a
<a href="https://github.com/jeremykendall/query-auth-impl">sample implementation</a> to
get you going.  If you find this helpful, or have any questions or comments,
please let me know.  If you find any horrible mistakes, please feel free to
submit an <a href="https://github.com/jeremykendall/query-auth/issues">issue</a> or a
<a href="https://github.com/jeremykendall/query-auth/pulls">pull request</a>, or you can
always submit the offending code to <a href="http://csiphp.com">CSI: PHP</a> :-)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Vagrant Synced Folders Permissions]]></title>
    <link href="https://jeremykendall.net/2013/08/09/vagrant-synced-folders-permissions/"/>
    <updated>2013-08-09T07:32:00-05:00</updated>
    <id>https://jeremykendall.net/2013/08/09/vagrant-synced-folders-permissions</id>
    <content type="html"><![CDATA[<p><em>UPDATE: Since writing this post Vagrant has changed the synced folder settings
and I&rsquo;ve come across a new (and better?) way of handling this problem. Scroll
down for the updates.</em></p>

<p>Having trouble getting your Synced Folders permissions just right in your
Vagrant + VirtualBox VM? They&rsquo;ve been giving me some grief lately. Here are the
(undocumented) <code>Vagrantfile</code> options that finally got it sorted out.</p>

<h3>Permissions Challenges</h3>

<p>The issue that got me digging into this was trying to get permissions just so
to allow my web apps to write logs.  As you probably know, apache (or your web
server of choice), sometimes needs write access to certain web application
directories.  I&rsquo;ve always take care of that by adding the apache user group to
the directories in question and then giving that user full access.  Doing that
in Ubuntu looks something like:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>chown -R jeremykendall.www-data /path/to/logs
</span><span class='line'>chmod 775 /path/to/logs
</span></code></pre></td></tr></table></div></figure>


<p>If you&rsquo;ve tried doing something similar in your Vagrant shared folders, you&rsquo;ve
likely failed.  This, as it turns out, <a href="https://github.com/mitchellh/vagrant/issues/897">doesn&rsquo;t work with VirtualBox shared folders</a>
&ndash; you have to make the changes in your <code>Vagrantfile</code>.</p>

<h3>Setting Permissions via the Vagrantfile</h3>

<p><em>UPDATE: Thanks to Joe Ferguson for <a href="http://jeremykendall.net/2013/08/09/vagrant-synced-folders-permissions/#comment-1118614212">pointing out in the comments</a>
that Vagrant has been upgraded and my example was no longer current.  Below are
both examples marked by Vagrant version.</em></p>

<p>Here&rsquo;s my new <code>synced_folder</code> setting in my <code>Vagrantfile</code>:</p>

<p>Vagrant v1.1+:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="c1"># Vagrant v1.1+</span>
</span><span class='line'>  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">synced_folder</span> <span class="s2">&quot;./&quot;</span><span class="p">,</span> <span class="s2">&quot;/var/sites/dev.query-auth&quot;</span><span class="p">,</span> <span class="nb">id</span><span class="p">:</span> <span class="s2">&quot;vagrant-root&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="ss">owner</span><span class="p">:</span> <span class="s2">&quot;vagrant&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="ss">group</span><span class="p">:</span> <span class="s2">&quot;www-data&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="n">mount_options</span><span class="p">:</span> <span class="o">[</span><span class="s2">&quot;dmode=775,fmode=664&quot;</span><span class="o">]</span>
</span></code></pre></td></tr></table></div></figure>


<p>Vagrant 1.0.x:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="c1"># Vagrant v1.0.x</span>
</span><span class='line'>  <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">synced_folder</span> <span class="s2">&quot;./&quot;</span><span class="p">,</span> <span class="s2">&quot;/var/sites/dev.query-auth&quot;</span><span class="p">,</span> <span class="nb">id</span><span class="p">:</span> <span class="s2">&quot;vagrant-root&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="ss">:owner</span> <span class="o">=&gt;</span> <span class="s2">&quot;vagrant&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="ss">:group</span> <span class="o">=&gt;</span> <span class="s2">&quot;www-data&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="ss">:extra</span> <span class="o">=&gt;</span> <span class="s2">&quot;dmode=775,fmode=664&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>I&rsquo;m sure you can immediately see what resolved the issue.  Lines 3 and 4 set
the owner and group, respectively, and line 5 sets directory and file modes
appropriately.  That simple fix was frustratingly difficult because I couldn&rsquo;t
find it documented <em>anywhere</em>. After much searching and opening far too many
browser tabs, I cobbled together the info above.  A quick <code>vagrant reload</code>
later and I was off to the races.</p>

<h3>UPDATE: Alternate Method</h3>

<p>An alternate method that doesn&rsquo;t include modifying your synced folder permissions is
changing the web user to the vagrant user.  Bad idea?  Security problem?  Not on your dev
VM it ain&rsquo;t, and that&rsquo;s good enough for me. Big thanks to Chris Tankersley for all
the help getting this one figured out.</p>

<div class='embed twitter'><blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/dragonmantank">@dragonmantank</a> Didn&#39;t you once tell me you set vagrant as the apache user and group on your Vagrant VMs?</p>&mdash; Jeremy Kendall (@JeremyKendall) <a href="https://twitter.com/JeremyKendall/status/383416513715523584">September 27, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></div>


<p>Chris and I both put together gists, and <a href="https://github.com/jeremykendall/flaming-archer/blob/develop/manifests/default.pp#L41-L53">this is how I&rsquo;m currently doing it</a>
in Flaming Archer, but probably the best method for changing the apache user
to the vagrant user comes from the <a href="https://github.com/Intracto/Puppet/blob/master/apache2/manifests/init.pp">Intracto Puppet apache manifest</a>.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1"># Source https://raw.github.com/Intracto/Puppet/master/apache2/manifests/init.pp</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Change user</span>
</span><span class='line'><span class="nb">exec</span> <span class="p">{</span> <span class="s2">&quot;ApacheUserChange&quot;</span> <span class="p">:</span>
</span><span class='line'>    <span class="n">command</span> <span class="o">=&gt;</span> <span class="s2">&quot;sed -i &#39;s/APACHE_RUN_USER=www-data/APACHE_RUN_USER=vagrant/&#39; /etc/apache2/envvars&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="n">onlyif</span>  <span class="o">=&gt;</span> <span class="s2">&quot;grep -c &#39;APACHE_RUN_USER=www-data&#39; /etc/apache2/envvars&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="nb">require</span> <span class="o">=&gt;</span> <span class="no">Package</span><span class="o">[</span><span class="s2">&quot;apache2&quot;</span><span class="o">]</span><span class="p">,</span>
</span><span class='line'>    <span class="n">notify</span>  <span class="o">=&gt;</span> <span class="no">Service</span><span class="o">[</span><span class="s2">&quot;apache2&quot;</span><span class="o">]</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="c1"># Change group</span>
</span><span class='line'><span class="nb">exec</span> <span class="p">{</span> <span class="s2">&quot;ApacheGroupChange&quot;</span> <span class="p">:</span>
</span><span class='line'>    <span class="n">command</span> <span class="o">=&gt;</span> <span class="s2">&quot;sed -i &#39;s/APACHE_RUN_GROUP=www-data/APACHE_RUN_GROUP=vagrant/&#39; /etc/apache2/envvars&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="n">onlyif</span>  <span class="o">=&gt;</span> <span class="s2">&quot;grep -c &#39;APACHE_RUN_GROUP=www-data&#39; /etc/apache2/envvars&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="nb">require</span> <span class="o">=&gt;</span> <span class="no">Package</span><span class="o">[</span><span class="s2">&quot;apache2&quot;</span><span class="o">]</span><span class="p">,</span>
</span><span class='line'>    <span class="n">notify</span>  <span class="o">=&gt;</span> <span class="no">Service</span><span class="o">[</span><span class="s2">&quot;apache2&quot;</span><span class="o">]</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Additionally, if you&rsquo;re copying and pasting from anywhere, don&rsquo;t forget to change
the apache lockfile permissions:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1"># Source https://github.com/Intracto/Puppet/blob/master/apache2/manifests/init.pp</span>
</span><span class='line'>
</span><span class='line'><span class="nb">exec</span> <span class="p">{</span> <span class="s2">&quot;apache_lockfile_permissions&quot;</span> <span class="p">:</span>
</span><span class='line'>    <span class="n">command</span> <span class="o">=&gt;</span> <span class="s2">&quot;chown -R vagrant:www-data /var/lock/apache2&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="nb">require</span> <span class="o">=&gt;</span> <span class="no">Package</span><span class="o">[</span><span class="s2">&quot;apache2&quot;</span><span class="o">]</span><span class="p">,</span>
</span><span class='line'>    <span class="n">notify</span>  <span class="o">=&gt;</span> <span class="no">Service</span><span class="o">[</span><span class="s2">&quot;apache2&quot;</span><span class="o">]</span><span class="p">,</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>ACL on Shared Folders That Are Not NFS</h3>

<p>One of the reasons the above methods are necessary is that you can&rsquo;t use ACLs
on shared directories.  If none of the above options appeal to you, it&rsquo;s possible
to use ACLs on your VM as long as the directories aren&rsquo;t shared. For more information,
see <a href="https://github.com/puphpet/puphpet/issues/138#issuecomment-25434178">Frank Stelzer&rsquo;s comment</a>
regarding <code>setfacl</code> on a Vagrant box.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[I Love You Guys]]></title>
    <link href="https://jeremykendall.net/2013/08/07/i-love-you-guys/"/>
    <updated>2013-08-07T06:50:00-05:00</updated>
    <id>https://jeremykendall.net/2013/08/07/i-love-you-guys</id>
    <content type="html"><![CDATA[<p>Tuesday was a frustrating day at work, one I spent chasing a bug that I
was never able to find. My friends on Twitter made it all better.</p>

<div class='embed twitter'><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Looks like my day will be spent hunting an E_USER_GHOST_IN_MACHINE error.</p>&mdash; Jeremy Kendall (@JeremyKendall) <a href="https://twitter.com/JeremyKendall/status/364755019599327232">August 6, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></div>




<div class='embed twitter'><blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/JeremyKendall">@JeremyKendall</a> no ghostBusters::bust(); ?</p>&mdash; Muhammad Shoaib (@_shoaibi) <a href="https://twitter.com/_shoaibi/status/364757038879866884">August 6, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></div>




<div class='embed twitter'><blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/JeremyKendall">@JeremyKendall</a> Careful not to let it escalate to an E_FIST_IN_MACHINE fatal error!</p>&mdash; Michael Moussa (@michaelmoussa) <a href="https://twitter.com/michaelmoussa/status/364822162156167169">August 6, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></div>




<div class='embed twitter'><blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/michaelmoussa">@michaelmoussa</a> I think that&#39;s a warning. E_SHOTGUN is the fatal one. /cc <a href="https://twitter.com/JeremyKendall">@JeremyKendall</a></p>&mdash; David Weinraub (@papayasoft) <a href="https://twitter.com/papayasoft/status/364989981334323201">August 7, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></div>




<div class='embed twitter'><blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/papayasoft">@papayasoft</a> <a href="https://twitter.com/michaelmoussa">@michaelmoussa</a> Turned out it was just a notice: E_DEV_CHASES_TAIL. I hate when that happens.</p>&mdash; Jeremy Kendall (@JeremyKendall) <a href="https://twitter.com/JeremyKendall/status/365089987387064321">August 7, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></div>




<div class='embed twitter'><blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/JeremyKendall">@JeremyKendall</a> I hate when that happens! Btw, you can avoid future occurrences by setting set &quot;lol_noob = Off&quot; in your php.ini. <a href="https://twitter.com/papayasoft">@papayasoft</a></p>&mdash; Michael Moussa (@michaelmoussa) <a href="https://twitter.com/michaelmoussa/status/365090940257439744">August 7, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></div>




<div class='embed twitter'><blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/JeremyKendall">@JeremyKendall</a> just set the following: error_reporting(E_ALL ^ E_PROBABLY_IE); problem solved...</p>&mdash; Jonathon Suggs (@jonathonsuggs) <a href="https://twitter.com/jonathonsuggs/status/365124671202525184">August 7, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Number of the Contributor]]></title>
    <link href="https://jeremykendall.net/2013/08/05/number-of-the-contributor/"/>
    <updated>2013-08-05T09:30:00-05:00</updated>
    <id>https://jeremykendall.net/2013/08/05/number-of-the-contributor</id>
    <content type="html"><![CDATA[<p>My contributions at work, Aug 05 2012 - Aug 05 2013.</p>

<p><img src="https://jeremykendall.net/images/666-contributions-annotated.png"></p>

<blockquote><p>Woe to you, o earth and sea, for the devil sends the beast with wrath, because he knows the time is short … Let him who hath understanding reckon the number of the beast: for it is a human number; its number is six hundred and sixty six.</p><footer><strong>Iron Maiden</strong> <cite><a href='http://www.youtube.com/watch?v=jsmcDLDw9iw'>The Number of the Beast</a></cite></footer></blockquote>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Composer Kerfuffle]]></title>
    <link href="https://jeremykendall.net/2013/07/12/the-composer-kerfuffle/"/>
    <updated>2013-07-12T09:21:06-05:00</updated>
    <id>https://jeremykendall.net/2013/07/12/the-composer-kerfuffle</id>
    <content type="html"><![CDATA[<p>Wednesday night I discovered, much to my shock and dismay, that <a href="http://getcomposer.org/">Composer</a>&rsquo;s install command now defaults to installing development dependencies along with a project&rsquo;s required dependencies.  That discovery prompted me to start a &ldquo;<a href="http://seld.be/notes/composer-installing-require-dev-by-default">small twitter shitstorm</a>&rdquo; with <a href="https://twitter.com/jeremykendall/status/355148025393446913">this tweet</a>:</p>

<div class='embed twitter'><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Since when does &#39;composer install&#39; install dev dependencies by default?  I know &#39;composer update&#39; does that, but install? /cc <a href="https://twitter.com/seldaek">@seldaek</a></p>&mdash; Jeremy Kendall (@JeremyKendall) <a href="https://twitter.com/JeremyKendall/status/355148025393446913">July 11, 2013</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script></div>


<p>Before I delve into why I&rsquo;m shocked and dismayed, I want to say a few things about Composer and the Composer team.  In all of my years of programming in PHP, I&rsquo;m not sure there&rsquo;s been a more important, more game changing, or more exciting project than Composer.  Being able to easily manage project dependencies has revolutionized the way I develop.  Composer, and the related <a href="https://packagist.org/">packagist.org</a>, have been a larger quality-of-life improvement for me than any other tool I&rsquo;ve added to my toolkit over the years.  I&rsquo;d like to extend my sincerest thanks to <a href="http://naderman.de/">Nils Adermann</a>, <a href="http://nelm.io/jordi">Jordi Boggiano</a> and the many <a href="https://github.com/composer/composer/graphs/contributors">community contributors</a> who have worked so hard and so diligently to make Composer a reality.</p>

<p><strong>My Beef with the Change</strong></p>

<p><strong>1. There was never any public discussion about the change</strong></p>

<p>Beyond a few brief asides in a couple of github <a href="https://github.com/composer/composer/issues/1005">issues</a> and <a href="https://github.com/composer/composer/pull/1833">pull requests</a>, I can&rsquo;t find anywhere this change discussed publicly.  For a project of this size and this importance, removing the community from the decision making process was a terrible mistake.  I&rsquo;d much prefer to have argued all of this before the change than after.</p>

<p>Yesterday, Jordi posted <a href="http://seld.be/notes/composer-installing-require-dev-by-default">&ldquo;Composer: Installing require-dev by default&rdquo;</a> to explain his rationale for the change.  One of his points is that <a href="https://github.com/composer/composer/releases/tag/1.0.0-alpha7">he made a note in the 1.0.0-alpha changelog</a> regarding the upcoming change.  While this is true, I find it insufficient.  I rarely read changelogs (my bad), but I certainly don&rsquo;t read changelogs to discover what&rsquo;s coming in the future.  That&rsquo;s what road maps, blog posts, and PRs are for.  Putting that note in the changelog was &ldquo;too little, too early&rdquo;.</p>

<p><strong>2. Composer philosophy and workflow has always been, &ldquo;install for production, update for development&rdquo;</strong></p>

<p>The longstanding Composer rule of thumb has always been &ldquo;install for production, update for development&rdquo;.  <a href="http://adamcod.es/2013/03/07/composer-install-vs-composer-update.html">Adam Brett&rsquo;s post on Composer workflow</a> and the difference between update and install is a good example of this rule of thumb.  Humorously enough, Jordi reinforces that rule of thumb (while defending the change that composer update installs dev requirements by default) in his <a href="http://seld.be/notes/composer-an-update-on-require-dev">blog post</a> <em>immediately prior</em> to the post defending the composer install change:</p>

<blockquote><p>&ldquo;The install command on the hand remains the same. It does not install dev dependencies by default, and it will actually remove them if they were previously installed and you run it without &ndash;dev. Again this makes sense since in production you should only run install to get the last verified state (stored in composer.lock) of your dependencies installed.&rdquo;</p></blockquote>

<p>That rule of thumb is now turned on its head, and the default &ldquo;composer install in production&rdquo; advice now needs updating, careful warnings, and caveats.</p>

<p><strong>3. Tools should never default to dev (unless they&rsquo;re meant for dev, of course)</strong></p>

<p>This is a philosophical point on my part, but it&rsquo;s one I don&rsquo;t think is unique to me and it&rsquo;s one that I think can be well defended.  My point here is that one should always write code and tools in such a way that deployments to production will only ever result in production code being deployed.  Clear as mud?  Let me try with an example.</p>

<p>I frequently use environment variables to allow my applications to detect which environment they&rsquo;re running in.  If those environment variables don&rsquo;t exist, then the application should default to production.  Why?  Because dev environments are the special case, not production, and it&rsquo;s far too easy to forget to add those environment variables when deploying.  I make my life easier by making the production environment as idiot-proof as possible, and not the other way around.</p>

<p>This philosophy was in place in the prior behavior of composer install (and composer update, for that matter).  Now that it&rsquo;s changed, the production environment is far more likely to suffer than the development environment.  Forgetting to add the &ndash;dev flag in development is a lot less (potentially) costly than forgetting to add the &ndash;no-dev flag in production.</p>

<p>In a seeming contradiction, I&rsquo;ve said that <a href="https://twitter.com/jeremykendall/status/355186613376126976">I have no problem with composer update defaulting to installing dev dependencies</a>.  I&rsquo;ve gone back and forth on that a bit when considering my &ldquo;tools should never default to dev&rdquo; position, but I don&rsquo;t think I&rsquo;m being inconsistent here.  Since the rule of thumb encourages using update in development and <em>never</em> in production, then update becomes a dev tool which can safely default to installing development dependencies.  Having said that, if consistency between commands is important, then composer update should no longer default to dev and the changes to both install and update should be reverted.</p>

<p><strong>In Closing</strong></p>

<p>Composer has become an integral part of my workflow, and a critical piece of the PHP development process in general.  I loved Composer before this change and I&rsquo;ll love Composer after.  That said, changing the Composer command that is intended primarily for production use is extremely disruptive and a very bad call, especially considering how the change came about.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Piedmont Natural Gas: Customer Service WIN]]></title>
    <link href="https://jeremykendall.net/2012/12/02/piedmont-natural-gas-customer-service-win/"/>
    <updated>2012-12-02T18:40:15-06:00</updated>
    <id>https://jeremykendall.net/2012/12/02/piedmont-natural-gas-customer-service-win</id>
    <content type="html"><![CDATA[<p><em>(This is the follow-up to yesterday&rsquo;s post, &ldquo;<a href="http://www.jeremykendall.net/2012/12/01/dear-piedmont-natural-gas/">Dear Piedmont Natural Gas</a>&rdquo;. Start there for the full story.)</em></p>

<p>As I write this follow-up post, the gas has been turned back on, my hot water heater is working away, and my wife and I find ourselves on the far side of a bad situation turned good.</p>

<p>We last left off with a phone call from <a href="http://www.piedmontng.com/">Piedmont</a> corporate and a promise to have our gas turned back on by 5 pm CST.  Not only did Piedmont come through, they came through big.  The technician they sent was early to the appointment and went above-and-beyond to make sure we were taken care of.  While I wish <a href="http://www.jeremykendall.net/2012/12/01/dear-piedmont-natural-gas/">this entire situation never happened</a>, the outcome is the very best of a bad situation, and I want to close this out with a big thanks to Piedmont Natural Gas.</p>

<p>Once Piedmont corporate learned about our problem, they went the extra mile to resolve it to our satisfaction as quickly as possible.  I don&rsquo;t know everything they did, but they went as far as reviewing the recordings of both our Friday and Saturday customer service phone calls, calling both my wife and myself to schedule reconnection, and taking the time to explain exactly what happened, why it happened, and then take responsibility for it.  Kudos to Piedmont.</p>

<p>Thanks also to all of you for being so supportive.  In the grand scheme of things, this was small potatoes, but that didn&rsquo;t make it any less upsetting.  The retweets, supportive comments, and personal commiserations went a long way towards making this a lot easier.</p>
]]></content>
  </entry>
  
</feed>
