<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Sentinel</title>
	<atom:link href="http://edgesentinel.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://edgesentinel.com</link>
	<description></description>
	<lastBuildDate>Mon, 13 Dec 2010 23:11:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>The Gawker Crack</title>
		<link>http://edgesentinel.com/2010/12/the-gawker-crack/</link>
		<comments>http://edgesentinel.com/2010/12/the-gawker-crack/#comments</comments>
		<pubDate>Mon, 13 Dec 2010 23:11:56 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[devel]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://edgesentinel.com/?p=79</guid>
		<description><![CDATA[There have been a flurry of posts about Gawker Media servers being broken into. Most articles have stayed above the technical details of how this happened, but after analyzing the actual data files in question, it appears the issue was Gawker&#8217;s reliance on Symmetric Encryption, specifically the DES cipher, and using it seemingly without salt. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://edgesentinel.com/wp-content/uploads/2010/12/MP900385309.jpg"><img src="http://edgesentinel.com/wp-content/uploads/2010/12/MP900385309-214x300.jpg" alt="" title="Lock &amp; Key" width="214" height="300" class="alignright size-medium wp-image-85" /></a>There have been a <a href="http://www.businessinsider.com/gawker-hacked-2010-12">flurry</a> <a href="http://www.huffingtonpost.com/2010/12/12/gawker-hack-hacked-databa_n_795613.html?ref=tw">of</a> <a href="http://blogs.villagevoice.com/runninscared/2010/12/alleged_gawker.php">posts</a> about Gawker Media servers being broken into. Most articles have stayed above the technical details of how this happened, but after analyzing the actual data files in question, it appears the issue was Gawker&#8217;s reliance on <a href="http://en.wikipedia.org/wiki/Symmetric-key_algorithm">Symmetric Encryption</a>, specifically the DES cipher, and using it seemingly without salt.</p>
<p>When building an authentication system, it is common practice not to store the actual password (e.g. <em>&#8220;opensesame&#8221;</em>) but instead to store an encrypted or obfuscated version which can be confirmed against the password but cannot be used elsewhere. The standard operating procedure is to employ a cryptographic hash, a one-way function that cannot be deciphered. A layman&#8217;s example of a hash function might be <code>hash(word) = (number of vowels) + (number of consonants)</code>, so <code>hash(opensesame) = 5 + 5 = 10</code>. As you can see, if someone submitted a password like &#8220;<em>letmein</em>&#8221; or &#8220;<em>password</em>&#8221; or &#8220;<em>123456</em>,&#8221; the system could count the vowels and consonants and determine whether there was a match, but do so without actually storing &#8220;<em>opensesame</em>&#8221; at all. Then, if miscreants broke into the database, they would know that your password has 5 vowels and 5 consonants, but they wouldn&#8217;t know the actual password, and if they tried to log into your Gmail or WordPress or Bank of America site they&#8217;d still have quite a task ahead of them.</p>
<p>Unfortunately, in this case it appears that instead of a one-way hash function, Gawker used a symmetric (i.e. <strong>two-way</strong>, i.e. <strong>reversible</strong>) function called DES. DES is fine (well, not really, it&#8217;s actually been deprecated for over a decade) for storing the passwords. What this means is that, if bad guys can determine the encryption key, they can decrypt the raw password and use it to log into other sites. If there were just a single key used, then the entire user list would be vulnerable as soon as someone found it.</p>
<p>Current forensic evidence suggests that Gawker did not use a single key across the board, but instead used the password itself as the encryption key, which does help avoid the problem of a single key being compromised. However, because encryption is predictable and deterministic, this also means that a given password will always encrypt to the same encrypted password, meaning once someone computes &#8220;<code>encrypt(opensesame)</code>&#8221; they can find all the other users who used that same password. That&#8217;s how the attackers published a list of all the users whose passwords were &#8220;password&#8221; or &#8220;qwerty&#8221; (a shockingly large number): They were looking at a table that looked something like:</p>
<table>
<tr>
<td>joe@hotmail.com</td>
<td>hf387d2_4us</td>
</tr>
<tr>
<td>mary@hotmail.com</td>
<td>hf387d2_4us</td>
</tr>
<tr>
<td>steve@yahoo.com</td>
<td>hf387d2_4us</td>
</tr>
<tr>
<td>&#8230;</td>
<td>hf387d2_4us</td>
</tr>
</table>
<p> and once they figure out what that string decrypts to, they know everybody&#8217;s password.</p>
<p>The recommendation to avoid this problem is to employ &#8220;<a href="http://en.wikipedia.org/wiki/Salt_%28cryptography%29"><em>salt</em></a>,&#8221; a random number that is added to each password before the encryption or decryption happens. With this in place, you&#8217;re not storing <code>encrypt(opensesame)</code> again and again, you&#8217;re storing <code>encrypt(opensesame+12345)</code> and <code>encrypt(opensesame+90210)</code> and <code>encrypt(opensesame+02138)</code>. The salt can be stored in plaintext in the database because it&#8217;s not providing actual security against decryption here, it&#8217;s simply fighting against one compromised password creating an advantage for deciphering a second one. In fact, the bigger problem it helps guard against is one known as &#8220;<a href="http://en.wikipedia.org/wiki/Rainbow_table">Rainbow Tables</a>,&#8221; which are basically pre-computed lists of encrypted passwords. Without salt, an attacker can build or buy a list of common passwords and compare the encrypted results against your database; with salt, these tables are mostly impractical.</p>
<p>This essay is not meant to criticize Gawker individually, but rather to use this attack to help teach others to avoid the same pitfalls.</p>
]]></content:encoded>
			<wfw:commentRss>http://edgesentinel.com/2010/12/the-gawker-crack/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hosting That Repository</title>
		<link>http://edgesentinel.com/2010/11/hosting-that-repository/</link>
		<comments>http://edgesentinel.com/2010/11/hosting-that-repository/#comments</comments>
		<pubDate>Mon, 08 Nov 2010 22:35:28 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://edgesentinel.com/?p=63</guid>
		<description><![CDATA[Several weeks back setting up a local repository for .deb packages. Well we&#8217;re growing and adding machines, so it was time to move that local repository to a centralized location. It shouldn&#8217;t be hard, but it did have a few more steps than I hoped. The essence was around building the repository through a framework, [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
li pre {
   background-color:#505050;
   color: #99ff66;
   margin-left: 2em;
   padding-left: 1em;
}
</style>
<p><img src="http://edgesentinel.com/wp-content/uploads/2010/11/archives-293x300.jpg" alt="Collection of file boxes symbolizing .deb packages" title="archives" width="293" height="300" class="alignright size-medium wp-image-70" /><br />
Several weeks back <a href="http://edgesentinel.com/2010/08/hosting-deb-packages-locally/">I wrote about</a> setting up a local repository for <code>.deb</code> packages. Well we&#8217;re growing and adding machines, so it was time to move that local repository to a centralized location.</p>
<p>It shouldn&#8217;t be hard, but it did have a few more steps than I hoped. The essence was around building the repository through a framework, and for that, a <a href="http://www.mail-archive.com/debian-mentors@lists.debian.org/msg68069.html">number</a> <a href="http://www.danielbond.org/archives/114">of</a> <a href="http://www.jejik.com/articles/2006/09/setting_up_and_managing_an_apt_repository_with_reprepro/">posts</a> led me to <a href="http://mirrorer.alioth.debian.org/">reprepro</a>.</p>
<p>According to its man page and sparse documentation, <code>reprepro</code> is &#8220;a tool to handle local repositories of debian packages,&#8221; which sounded exactly like what I wanted. </p>
<p>The steps were fairly straightforward, albeit with one gotcha that took me about an hour to puzzle through.</p>
<h3>Build the package</h3>
<p>The first step is an obvious prerequisite. However, one step missing from what I described in <a href="http://edgesentinel.com/2010/08/building-custom-deb-packages/">Building Custom .deb Packages and Chroots</a> was the requirement to specify <code>Section</code> (e.g. <code>Main</code>, <code>non-free</code>, etc.) and <code>Priority</code> sections. Without this, reprepro will give the cryptic (though, in retrospect, obvious) error &#8220;No section given.&#8221; (Maybe if the &#8216;s&#8217; was capitalized I wouldn&#8217;t have assumed this was based on the reprepro config file, instead of the package itself). Oh well.</p>
<h3>Create a repository</h3>
<p><a href="http://joseph.ruscio.org/blog/2010/08/19/setting-up-an-apt-repository/">Joseph Ruscio</a> explains this part pretty well; in essence, you:</p>
<ol>
<li><strong>Generate the PGP key</strong>: <code>gpg --gen-key</code> should get you pretty much all you need here. If you want the repository to be owned by another user, you&#8217;ll have to sudo into that account and ensure that user has a ~username directory (which system accounts will not, by default)</li>
<li><strong>Create the repository control files</strong>: At the minimum, reprepro will need a subdirectory called <code>conf</code> underneath wherever your repository will live. Inside that dir, create a file <code>distributions</code> that contains the reprepro setup. Here&#8217;s mine, to diff against the other online examples:
<pre>
Origin: <em>http://myhostname.path.com</em>
Label: <em>Edge Apt Repository</em>
Codename: <em>es</em>
Architectures: i386 amd64
Components: non-free
Description: <em>A generic description.</em>
SignWith: yes
</pre>
<p>Details of the various settings are in <a href="http://mirrorer.alioth.debian.org/reprepro.1.html">the man page</a>; I think these are the only mandatory ones.</li>
<li><strong>Create an <code>options</code> file</strong>: If you want to save yourself some command-line time, you can create a <code>conf/options</code> file like so:
<pre>
verbose
ask-passphrase
basedir .
</pre>
</li>
<li><strong>Run reprepro</strong>: The command is simple:
<pre>reprepro includedeb <em>[codename]</em> <em>[path to .deb file]</em></pre>
</li>
<li><strong>Make the repository available over http</strong>: The various articles linked above show how to set up a virtual host or path pointing to your new repository. For security purposes you should hide the <code>conf</code> and <code>db</code> directories from the public, and depending on how broadly you&#8217;re allowing distribution, play with your webserver&#8217;s permissions to restrict by IP, domain, or password. Basically, you just need to make sure that <code>apt</code> on your client machine (where you&#8217;re installing <strong>to</strong>) can browse the directory you&#8217;ve created above.</li>
<li><strong>Edit <code>/etc/apt/sources.list</code> on the client machine(s)</strong>: You&#8217;ll simply add a row to point to this new directory, the codename you specified, and the source you specified in the package (e.g. <code>non-free</code>). Here&#8217;s mine:
<pre>deb http://myhostname.edgesentinel.com/</pre>
</li>
<li><strong>apt-get update</strong></li>
</ol>
<p><br/><br />
And that&#8217;s it!<br />
Happy distributing.</p>
<p>/m</p>
]]></content:encoded>
			<wfw:commentRss>http://edgesentinel.com/2010/11/hosting-that-repository/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>He&#8217;s Having a (H)MAC Attack!</title>
		<link>http://edgesentinel.com/2010/10/hes-having-a-hmac-attack/</link>
		<comments>http://edgesentinel.com/2010/10/hes-having-a-hmac-attack/#comments</comments>
		<pubDate>Mon, 25 Oct 2010 00:41:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://edgesentinel.com/?p=52</guid>
		<description><![CDATA[In building a stateless web services API (e.g. a RESTful one), developers often must consider the chance that an attacker might attempt to spoof a call on behalf of a legitimate client. For example, if the attacker—Evil Enterprises—were to spoof a request to an event logging API used legitimately by Alpha Incorporated with garbage or [...]]]></description>
			<content:encoded><![CDATA[<p>In building a stateless web services API (e.g. a <a href="http://en.wikipedia.org/wiki/REST">RESTful one</a>), developers often must consider the chance that an attacker might attempt to spoof a call on behalf of a legitimate client. For example, if the attacker—Evil Enterprises—were to spoof a request to an event logging API used legitimately by Alpha Incorporated with garbage or inaccurate values, all sorts of data integrity issues might ensue.<a href="http://edgesentinel.com/wp-content/uploads/2010/10/mac-attack.jpg"><img class="alignright size-medium wp-image-53" title="mac attack" src="http://edgesentinel.com/wp-content/uploads/2010/10/mac-attack-300x296.jpg" alt="Classic McDonald's Big Mac Attack ad" width="300" height="296" /></a></p>
<p>To guard against this type of spoofing, many APIs require a &#8220;Message Authentication Code&#8221; (MAC) to be provided along with the API call, allowing the server to identify that a) the message originated from whom it is claimed to, b) that the message has not been modified in transit, and optionally c) that the message has not been previously submitted (i.e. &#8220;replayed&#8221;). However, many implementers—including some of the <a href="http://netifera.com/research/flickr_api_signature_forgery.pdf">most famous sites</a>—have made the naive assumption that an MD5 signature of the parameters of the request—i.e. <code>signature=md5(key + param1 + param2 ... param<em>n</em>)</code>—can provide these guarantees.</p>
<p>The trouble with the above formula, however, is that most hash functions, MD5 very much included, are have &#8220;second preimage vulnerabilities,&#8221; meaning that, given <code>Hash1 = hash(M1)</code> it is computationally possible to find a second message, <code>M2</code>, that yields the same hash value. In this case, given the signature, <code>S</code>, from a captured, legitimate request, an attacker can come up with extra text (a.k.a. &#8220;chaff&#8221;) <code>C</code> such that the hash function&#8217;s output even without the secret key is a known valid hash of the original request <code>S = MD5(key + param1 + param2) = MD5(param100 + param101 + C)</code>.</p>
<p>Moreover, switching the sequence of the MAC generator function to <code>signature=md5(param1 + param2 ... param<em>n</em> <strong>+ key</strong>)</code> (i.e. a &#8220;secret suffix&#8221;) still leaves the vulnerability that if the attacker can find a collision in the hash function, he knows that he&#8217;ll still have a collision when he appends the secret. Thus the security of the MAC is illusory.</p>
<p>The solution, as codified in <a href="http://www.ietf.org/rfc/rfc2104.txt">RFC 2104</a>, involves padding the originating message and computing both an outer and an inner hash. From <a href="http://en.wikipedia.org/wiki/HMAC#Definition_.28from_RFC_2104.29">Wikipedia</a>&#8230;</p>
<blockquote><p>Let:</p>
<ul>
<li><strong>H</strong>(·) be a cryptographic hash function</li>
<li><em>K</em> be a secret key padded to the right with extra zeros to the block size of the hash function</li>
<li><em>m</em> be the message to be authenticated</li>
<li>∥ denote <a title="Concatenation" href="/wiki/Concatenation">concatenation</a></li>
<li>⊕ denote <a title="Exclusive or" href="/wiki/Exclusive_or">exclusive or</a> (XOR)</li>
<li>opad be the outer padding (0x5c5c5c…5c5c, one-block-long <a title="Hexadecimal" href="/wiki/Hexadecimal">hexadecimal</a> constant)</li>
<li>ipad be the inner padding (0&#215;363636…3636, one-block-long <a title="Hexadecimal" href="/wiki/Hexadecimal">hexadecimal</a> constant)</li>
</ul>
<p>Then <strong>HMAC</strong>(<em>K</em>,<em>m</em>) is mathematically defined by <strong>HMAC</strong>(<em>K</em>,<em>m</em>) = <strong>H</strong><big><big>(</big></big>(<em>K</em> ⊕ opad) ∥ <strong>H</strong><big>(</big>(<em>K</em> ⊕ ipad) ∥ m<big>)<big>)</big></big>.</p></blockquote>
<p>In this way, the signature of the message can be made robust against spoofing, and can even remain strong despite the <a href="http://en.wikipedia.org/wiki/MD5#Collision_vulnerabilities">known collision vulnerabilities</a> against MD5 and SHA1. That said, anybody implementing a new system should skip over MD5 and SHA1 and go straight to HMAC-SHA256.</p>
]]></content:encoded>
			<wfw:commentRss>http://edgesentinel.com/2010/10/hes-having-a-hmac-attack/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VMware Tools on Ubuntu Server 10.04</title>
		<link>http://edgesentinel.com/2010/09/vmware-tools-on-ubuntu-server-10-04/</link>
		<comments>http://edgesentinel.com/2010/09/vmware-tools-on-ubuntu-server-10-04/#comments</comments>
		<pubDate>Thu, 02 Sep 2010 23:14:50 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://edgesentinel.com/?p=44</guid>
		<description><![CDATA[All of the help I could find for setting up Ubuntu in a VM (using VMware Fusion on my Mac) assumes you&#8217;re using the Desktop version, with all the pretty Gnome/Nautilus crap prettiness. In case anybody else gets stuck trying to install the VMware Tools (to provide useful features like access to your host (Mac) [...]]]></description>
			<content:encoded><![CDATA[<p>All of the help I could find for setting up Ubuntu in a VM (using VMware Fusion on my Mac) assumes you&#8217;re using the Desktop version, with all the pretty Gnome/Nautilus <strike>crap</strike> prettiness. In case anybody else gets stuck trying to install the VMware Tools (to provide useful features like access to your host (Mac) filesystem and clipboard sharing), here&#8217;s the steps: </p>
<ol>
<li>In Fusion, select <code>Virtual Machine | Install VMware Tools...</code> menu option. This option emulates a CDROM being inserted, but without Nautilus your guest OS won&#8217;t do anything until you&#8230;</li>
<li>Mount the CDROM by typing <code>sudo mount /dev/cdrom /mnt</code> (substitute <code>/mnt</code> if you want the mount point to be elsewhere)</li>
<li><code>cd /mnt</code> (or wherever your mount point was)</li>
<li><code>cp VMwareTools* ~/</code> to copy the archive to your home directory</li>
<li><code>cd</code> to move yourself to that home directory</li>
<li><code>umount /mnt</code> to unmount the CDROM</li>
<li><code>tar zxf VMwareTools*</code> to uncompress the archive</li>
<li><code>cd vmware-tools-distrib</code> to get into the contents</li>
<li>And finally, <code>sudo ./vmware-install.pl</code> to run the installer</li>
</ol>
<p>At this point the installer will walk you through the options; I just accepted all the defaults. </p>
<p>To turn on shared folders, go to the <code>Virtual Machine | Shared Folders</code> menu and configure from there. The vmware tools daemon should detect the changes and make those folders appear under <code>/mnt/hgfs</code> (which stands for <strong>H</strong>ost <strong>G</strong>uest <strong>F</strong>ile<strong>S</strong>ystem).</p>
<p>Good luck.<br />
/m</p>
]]></content:encoded>
			<wfw:commentRss>http://edgesentinel.com/2010/09/vmware-tools-on-ubuntu-server-10-04/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>What&#8217;s In a Name?</title>
		<link>http://edgesentinel.com/2010/09/whats-in-a-name/</link>
		<comments>http://edgesentinel.com/2010/09/whats-in-a-name/#comments</comments>
		<pubDate>Thu, 02 Sep 2010 22:33:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[devel]]></category>

		<guid isPermaLink="false">http://edgesentinel.com/?p=41</guid>
		<description><![CDATA[We&#8217;re hard at work on product design and development, fundraising, and build-out, but still don&#8217;t have the perfect name. So I built a naming tool to help myself, and made it public to help others. It&#8217;s fairly simple, taking a user-supplied dictionary of terms, concatenating them with random prefixes and suffixes, and checking the WHOIS. [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re hard at work on product design and development, fundraising, and build-out, but still don&#8217;t have the perfect name. So I built a naming tool to help myself, and made it public to help others. It&#8217;s fairly simple, taking a user-supplied dictionary of terms, concatenating them with random prefixes and suffixes, and checking the WHOIS. Probably won&#8217;t come up with the perfect name itself, but it does help get the brainstorming going. </p>
<p><a href="http://lab1.edgesentinel.com/namer">Check it out</a>.</p>
<p>/m</p>
]]></content:encoded>
			<wfw:commentRss>http://edgesentinel.com/2010/09/whats-in-a-name/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Static IP for VMWare Fusion</title>
		<link>http://edgesentinel.com/2010/08/static-ip-for-vmware-fusion/</link>
		<comments>http://edgesentinel.com/2010/08/static-ip-for-vmware-fusion/#comments</comments>
		<pubDate>Fri, 27 Aug 2010 03:51:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://edgesentinel.com/?p=38</guid>
		<description><![CDATA[While trying to test an Apache installation running inside a VMWare Fusion instance, I found something irritating: Every time my Mac resumed from sleep, the IP address the guest OS used would increment by one, meaning whatever test scripts I was running from Safari or Firefox on my Mac would need to be adjusted to [...]]]></description>
			<content:encoded><![CDATA[<p>While trying to test an Apache installation running inside a VMWare Fusion instance, I found something irritating: Every time my Mac resumed from sleep, the IP address the guest OS used would increment by one, meaning whatever test scripts I was running from Safari or Firefox on my Mac would need to be adjusted to the new IP. Irritating.</p>
<p>The solution, fortunately, was quite simple, and came compliments of <a href="http://craig.dubculture.co.nz/blog/2009/11/10/how-do-i-change-the-dhcp-subnet-for-nat-on-vmware-fusion-3-0/">Craig Box</a>:</p>
<ol>
<li>Run <code>ifconfig</code> inside the guest OS (the Ubuntu image, in my case) to find the MAC address of your virtual adapter</li>
<li>Back on the Mac side, edit the bottom of <code>/Library/Application Support/VMware Fusion/vmnet8/dhcpd.conf</code> (outside the <i>&#8220;DO NOT MODIFY SECTION&#8221;</i> tags) to create a static assignment that looks like:

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">host developer-vm {
        hardware ethernet 00:0c:29:0e:5f:3f;
        fixed-address 192.168.139.100;
}</pre></div></div>

</li>
</ol>
<p>The only note is that whatever <code>fixed-address</code> you assign must be within the randomly-assigned class-C subnet that VMWare is already using (i.e. the 192.168.nnn.0/24 that you&#8217;ve been getting dynamic addresses within; mine is &#8220;139&#8243; above) ; if you need to change yours, that needs to be updated in <code>/Library/Application Support/VMware Fusion/networking</code></p>
<p>To restart the service, you can reboot your VM. Theoretically, you can also try<br />
<code>sudo "/Library/Application Support/VMware Fusion/boot.sh" --restart</code> and then trigger a DHCP Refresh within the VM, but that seemed like overkill to me&#8230;</p>
<p>Good luck!<br />
/m</p>
]]></content:encoded>
			<wfw:commentRss>http://edgesentinel.com/2010/08/static-ip-for-vmware-fusion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hosting .deb Packages Locally</title>
		<link>http://edgesentinel.com/2010/08/hosting-deb-packages-locally/</link>
		<comments>http://edgesentinel.com/2010/08/hosting-deb-packages-locally/#comments</comments>
		<pubDate>Wed, 25 Aug 2010 21:52:45 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[devel]]></category>

		<guid isPermaLink="false">http://edgesentinel.com/?p=21</guid>
		<description><![CDATA[As I described in , since we&#8217;re using Ubuntu we wanted to use the Ubuntu package management tools&#8212;apt and dpkg&#8212;to install our custom stuff. After I built the package, I wanted to use apt to install it, because while dpkg will identify the dependencies, it won&#8217;t install them (which is lame, but a documented gap). [...]]]></description>
			<content:encoded><![CDATA[<p>As I described in <a href="http://edgesentinel.com/2010/08/building-custom-deb-packages/">Building Custom .deb Packages and Chroots</a>, since we&#8217;re using Ubuntu we wanted to use the Ubuntu package management tools&mdash;<code>apt</code> and <code>dpkg</code>&mdash;to install our custom stuff. After I built the package, I wanted to use <code>apt</code> to install it, because while <code>dpkg</code> will identify the dependencies, it won&#8217;t install them (which is lame, but a documented gap).</p>
<p>To do this, we need to tell apt where to find my package, which means we have to create a repository. Don&#8217;t worry, this sounded like a big deal to me with custom ftp servers, but <code>apt/sources.list</code> already supports file-based repositories. </p>
<p>Two easy steps:</p>
<h3>Create the repository</h3>
<p>First you need to create a special file called <code>Packages.gz</code> which lists the available packages. It&#8217;s built using the utility program <code>dpkg-scanpackages</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">mark<span style="color: #000000; font-weight: bold;">@</span>desktop$ <span style="color: #c20cb9; font-weight: bold;">mkdir</span> repository
mark<span style="color: #000000; font-weight: bold;">@</span>desktop$ <span style="color: #c20cb9; font-weight: bold;">mv</span> mypackage-0.1.deb repository
mark<span style="color: #000000; font-weight: bold;">@</span>desktop$ <span style="color: #7a0874; font-weight: bold;">cd</span> repository
mark<span style="color: #000000; font-weight: bold;">@</span>desktop$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> dpkg-scanpackages . <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">gzip</span> <span style="color: #660033;">-9c</span> <span style="color: #000000; font-weight: bold;">&gt;</span> Packages.gz</pre></div></div>

<h3>Let <code>apt</code> know about your new repository</h3>
<p>Edit <code>/etc/apt/sources.list</code> to tell it about your new file. Here&#8217;s why mine (inside my chroot) looked like when I was done:</p>

<div class="wp_syntax">
<div class="wp_syntax_download">
<div class="wp_syntax_download_filename"><a name="file-/etc/apt/sources.list" href="#file-%2Fetc%2Fapt%2Fsources.list" title="/etc/apt/sources.list">/etc/apt/sources.list</a></div>
<div class="wp_syntax_download_actions">
<a href="http://edgesentinel.com/wp-content/plugins/wp-syntax-download-extension/wp-syntax-download-extension.php/21//etc/apt/sources.list">raw</a> <a href="http://edgesentinel.com/wp-content/plugins/wp-syntax-download-extension/wp-syntax-download-extension.php/21/download//etc/apt/sources.list">download</a>
</div>
</div>
<div class="code"><pre class="apt_sources" style="font-family:monospace;"><span style="color: #00007f;">deb</span> <span style="color: #009900;">http://us.archive.ubuntu.com/ubuntu/</span> lucid <span style="color: #b16000;">main</span> <span style="color: #b16000;">universe</span> <span style="color: #b16000;">multiverse</span>
<span style="color: #00007f;">deb</span> <span style="color: #009900;">file:/home/mrisher/repository/</span> /
<span style="color: #00007f;">deb-src</span> <span style="color: #009900;">http://us.archive.ubuntu.com/ubuntu/</span> lucid <span style="color: #b16000;">main</span></pre></div>
</div>

<p>After that, you&#8217;ll have to tell apt to refresh its cache:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">mark<span style="color: #000000; font-weight: bold;">@</span>desktop$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> update</pre></div></div>

<p>That&#8217;s it! Now you can install your local packages (assuming no namespace collision, but you&#8217;d want to be careful about that anyway) by simply typing</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">mark<span style="color: #000000; font-weight: bold;">@</span>desktop$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> mypackage</pre></div></div>

<p>I haven&#8217;t figured out how to deal with the unsigned package yet, but I&#8217;m not really sure I care.</p>
<p>/m</p>
]]></content:encoded>
			<wfw:commentRss>http://edgesentinel.com/2010/08/hosting-deb-packages-locally/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building Custom .deb Packages and Chroots</title>
		<link>http://edgesentinel.com/2010/08/building-custom-deb-packages/</link>
		<comments>http://edgesentinel.com/2010/08/building-custom-deb-packages/#comments</comments>
		<pubDate>Wed, 25 Aug 2010 20:58:31 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[devel]]></category>

		<guid isPermaLink="false">http://edgesentinel.com/?p=17</guid>
		<description><![CDATA[Since we&#8217;re running Ubuntu LTS 10.04 on our servers, it seemed appropriate to deploy our software using the built-in package management utilities. Overkill for now, but the added expense was small enough that it felt worthwhile (as opposed to gold-plating; the general admonition is to avoid building for scale until just before you have to). [...]]]></description>
			<content:encoded><![CDATA[<p>Since we&#8217;re running <a href="https://wiki.ubuntu.com/LucidLynx">Ubuntu LTS 10.04</a> on our servers, it seemed appropriate to deploy our software using the built-in package management utilities. Overkill for now, but the added expense was small enough that it felt worthwhile (as opposed to gold-plating; the general admonition is to avoid building for scale until just before you have to).</p>
<p>Ubuntu, being Debian-based,uses .deb packages and two tools: <a href="http://manpages.ubuntu.com/manpages/lucid/en/man8/apt.8.html">apt</a> and <a href="http://manpages.ubuntu.com/manpages/maverick/en/man1/dpkg.1.html">dpkg</a>. And, unfortunately, almost all of the HOWTOs out there are about repackaging someone else&#8217;s source code (available in a .dsc—Debian Source Code—file). These HOWTOs will point you to a program called <a href="http://manpages.ubuntu.com/manpages/lucid/en/man8/checkinstall.8.html">Checkinstall</a>, which basically monitors the results of a <code>make install</code> command to determine what goes where, then retroactively builds a .deb package for next time.</p>
<p>This didn&#8217;t quite work for me because I didn&#8217;t have a <code>make install</code> in my code. So I had to assemble my package by hand. Turns out it&#8217;s not all that difficult.</p>
<p>It&#8217;s pretty simple: For the simplest installation, create a directory structure with a special directory, <code>DEBIAN</code> and your target installation directories, à la:</p>
<blockquote><p>
-+ packagename/<br />
&#8212;-+ DEBIAN/<br />
&#8212;&#8212;&#8211;+ control<br />
&#8212;-+ usr/<br />
&#8212;&#8212;&#8211;+ local/<br />
&#8212;&#8212;&#8212;&#8212;+ bin/<br />
&#8212;&#8212;&#8212;&#8212;&#8212;-+ myfile<br />
&#8230;
</p></blockquote>
<p>.deb packages are described from that file <code>DEBIAN/control</code>. The syntax is documented in the <a href="http://manpages.ubuntu.com/manpages/lucid/man5/deb-control.5.html">Ubuntu man pages</a> and there are overviews at <a href="http://www.compdigitec.com/labs/2008/07/28/building-deb-packages-on-ubuntudebian/">this site</a> and in <a href="http://ubuntuforums.org/showpost.php?p=5246368&#038;postcount=2">in the forums</a>. With that documentation, all I really had to do was determine the dependencies. Fortunately, I had been keeping track during development of the required packages so I didn&#8217;t need to use <a href="http://www.perlmonks.org/?node_id=118617">this slick trick</a> to list all the current mod_perl modules (though I tested it and it worked like a champ).<br />
Editing the control file is fairly straightforward.</p>

<div class="wp_syntax">
<div class="wp_syntax_download">
<div class="wp_syntax_download_filename"><a name="file-DEBIAN/control" href="#file-DEBIAN%2Fcontrol" title="DEBIAN/control">DEBIAN/control</a></div>
<div class="wp_syntax_download_actions">
<a href="http://edgesentinel.com/wp-content/plugins/wp-syntax-download-extension/wp-syntax-download-extension.php/17/DEBIAN/control">raw</a> <a href="http://edgesentinel.com/wp-content/plugins/wp-syntax-download-extension/wp-syntax-download-extension.php/17/download/DEBIAN/control">download</a>
</div>
</div>
<div class="code"><pre class="text" style="font-family:monospace;">Package: apollo-api
Version: 0.1.0
Maintainer: 'Mark Risher &lt;mark@edgesentinel.com&gt;'
Description: Apache/mod_perl API for handling and logging events...
 [my long description]
Architecture: all
Depends: libapache2-mod-perl2, libapache2-request-perl, ...</pre></div>
</div>

<p>The final step was to test out the install, and for that I wanted to have a &#8220;clean room,&#8221; i.e. an out-of-the-box, default server setup so I could be really sure I wasn&#8217;t missing any dependencies. I considered downloading a fresh VM to use with VMWare Fusion, but ultimately decided that a <a href="http://en.wikipedia.org/wiki/Chroot">chroot jail</a> would be lighter weight and use less local disk space. For those who don&#8217;t want to click through to Wikipedia, a <code>chroot jail</code> is basically a directory (e.g. <code>/home/mrisher/lucid</code>) with a special shell. When you log into that special shell, <code>/</code> (i.e. root) is remapped to point to that directory, meaning that while you&#8217;re inside the shell, all files and directories are all relative to the chroot directory rather than your actual, live system. For example, <code>/etc/ld.so.cache</code> from within the chroot will actually show you <code>/home/mrisher/lucid/etc/ld.so.cache</code>. Make sense? Here&#8217;s an example:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">## Look at the ld.so cache on my &quot;real&quot; system
desktop:/home/mark$ ls -lrt /etc/ld.so.cache
-rw-r--r-- 1 root root 56599 2010-08-24 16:14 /etc/ld.so.cache
&nbsp;
## now log into the chroot and run the same command
desktop:/home/mark$ schroot -c lucid
(lucid)desktop:/home/mark$ ls -lrt /etc/ld.so.cache
-rw-r--r-- 1 root root 12964 Aug 25 01:46 /etc/ld.so.cache</pre></div></div>

<p>Notice in how the second time, I have a much smaller cache? That&#8217;s because the chroot is loading just a small subset of the modules, since it&#8217;s a fresh install. And the location of that ld.so.cache? It&#8217;s <code>/home/mrisher/lucid/etc/ld.so.cache</code>. Here&#8217;s where everything is mounted; notice the chroot thinks of itself as a <em>rootfs</em> device instead of a physical device.</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">desktop:/home/mark$ df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda1             39814552   3962772  33829280  11% /
...
&nbsp;
desktop:/home/mark$ schroot -c lucid
(lucid)desktop:/home/mark$ df
Filesystem           1K-blocks      Used Available Use% Mounted on
rootfs                39814552   3962772  33829280  11% /
...</pre></div></div>

<p>Okay, enough preamble. How do you set one up? With <code>debootstrap</code>, a program that downloads the necessary files from an Ubuntu or Debian mirror. I actually used a wrapper called <a href="http://manpages.ubuntu.com/manpages/lucid/en/man8/pbuilder.8.html">pbuilder</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">desktop:/$ sudo apt-get install pbuilder debootstrap schroot
...
desktop:/$ sudo pbuilder create
...</pre></div></div>

<p>&#8230;but I wish I had just gone directly into debootstrap like <a href="http://blog.sourcefrog.net/2009/09/setting-up-ubuntu-chroot-for.html">this</a></p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">desktop:/$ sudo apt-get install debootstrap schroot
...
desktop:/$ sudo mkdir /home/myroots
desktop:/$ sudo debootstrap lucid /home/myroots/lucid
...</pre></div></div>

<p>This will run for several minutes downloading all the necessary packages. You can possibly speed it up by specifying a smaller variant like &#8220;minbase,&#8221; which &#8220;only includes essential packages and apt&#8221;:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">desktop:/$ sudo debootstrap --variant=minbase lucid /home/myroots/lucid</pre></div></div>

<p>Now you need to tell schroot about this new directory of goodness. Edit <code>/etc/schroot/schroot.conf</code> to add something like:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">[lucid]
description=my new Lucid download
users=mrisher
root-users=mrisher
directory=/home/myroots/lucid
type=directory</pre></div></div>

<p>And now you should be able to load it. If all goes according to plan&#8230;</p>

<div class="wp-terminal">mark@desktop:$ schroot -c lucid<br/></div>

<p>&#8230;will dump you into a new shell where <code>/</code> is mounted in the directory you just downloaded. It will mount your home directory, but it won&#8217;t inherit permissions; for example, this chroot has a new <code>/etc/sudoers</code> file so, by default, you won&#8217;t have sudo.</p>
<p>Now, from here, you can get to work installing your package to make sure there are no implicit dependencies.</p>
<p>Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://edgesentinel.com/2010/08/building-custom-deb-packages/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>mod_perl and PerlChildInitHandler</title>
		<link>http://edgesentinel.com/2010/08/mod_perl-and-perlchildinithandler/</link>
		<comments>http://edgesentinel.com/2010/08/mod_perl-and-perlchildinithandler/#comments</comments>
		<pubDate>Wed, 25 Aug 2010 16:18:17 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[devel]]></category>

		<guid isPermaLink="false">http://edgesentinel.com/?p=8</guid>
		<description><![CDATA[mod_perl provides a number of server lifecycle handlers, which allow you to hook various parts of the initiation sequence to log configuration files or logging before Apache starts handling your individual requests. Unfortunately, for reasons still not clear, when I tried to run initialization in the PerlChildInitHandler, it would correctly initialize but then the values [...]]]></description>
			<content:encoded><![CDATA[<p>mod_perl provides a number of <a href="http://perl.apache.org/docs/2.0/user/handlers/server.html">server lifecycle handlers</a>, which allow you to hook various parts of the initiation sequence to log configuration files or logging before Apache starts handling your individual requests. Unfortunately, for reasons still not clear, when I tried to run initialization in the <code>PerlChildInitHandler</code>, it would correctly initialize but then the values would get re-initialized back to defaults when the <code>PerlReponseHandler</code> fired.</p>
<p>The solution, and not all that satisfying, was to switch to the <code>PerlPostConfigHandler</code>, which did not suffer from that problem and has the added benefit of using shared memory across the multiple processes.</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">PerlModule Handler
PerlModule Apache2::Reload
PerlOpenLogsHandler Handler::open_logs
PerlPostConfigHandler Handler::post_config
PerlSetVar ReloadDirectories ¨/mnt/hgfs/src/api/lib¨
&lt;<span style="color: #000000; font-weight:bold;">Location</span> /event&gt;
   <span style="color: #00007f;">SetHandler</span> modperl   
   PerlResponseHandler Handler::handler
   PerlInitHandler Apache2::Reload
&lt;/<span style="color: #000000; font-weight:bold;">Location</span>&gt;</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://edgesentinel.com/2010/08/mod_perl-and-perlchildinithandler/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

