<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://stbenjam.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://stbenjam.github.io/" rel="alternate" type="text/html" /><updated>2026-06-06T21:50:33+00:00</updated><id>https://stbenjam.github.io/feed.xml</id><title type="html">Stephen Benjamin</title><subtitle>Software Developer at Red Hat. Working on OpenShift, Kubernetes, and AI-assisted tools.</subtitle><entry><title type="html">Your AI Agent Needs Its Own Identity</title><link href="https://stbenjam.github.io/2026/06/05/separating-agent-identity.html" rel="alternate" type="text/html" title="Your AI Agent Needs Its Own Identity" /><published>2026-06-05T08:38:00+00:00</published><updated>2026-06-05T08:38:00+00:00</updated><id>https://stbenjam.github.io/2026/06/05/separating-agent-identity</id><content type="html" xml:base="https://stbenjam.github.io/2026/06/05/separating-agent-identity.html"><![CDATA[<p>When people talk about running AI agents autonomously, the conversation usually centers on sandboxing: what can the agent access, what damage can it do, how do you contain the blast radius. These are important questions. But there’s a deeper problem lurking underneath them.</p>

<p><strong>Identity.</strong> Who or what is doing this thing?</p>

<p>The problem is not just that agents need fewer permissions. It’s that they need legible, revocable, delegated identities of their own. A separate account is not the solution, but it is the least-bad approximation we have today.</p>

<h2 id="the-progression">The progression</h2>

<p>Most people’s journey with AI agents follows a predictable arc. You start by <strong>copying and pasting</strong> from a chat window. Then you’re <strong>babysitting</strong> a local agent, approving every action. Then it’s <strong>sandboxed</strong> in a container, scoped to one repo, running tests on its own. Then one night you <strong>go to bed</strong> and let it noodle on a problem unsupervised.</p>

<p>At each step, the agent does more under your name. Complex changes still need nudging, but more and more I’m emboldened to let it run on its own. If it’s still using your credentials, every action is attributed to you, and you might not know what happened until morning. Or worse, Claude found the JWT token in <code class="language-plaintext highlighter-rouge">~/Downloads</code> for your production BigQuery database and helpfully ran a query that dropped the wrong table. Least privilege matters. My agents live in their own bubbles, with access scoped so mistakes are recoverable and attributable.</p>

<p>But even with proper sandboxing, identity breaks. Operationally, the agent behaves less like an extension of my hands and more like an independent actor.</p>

<blockquote>
  <p><strong>A note on autonomy:</strong> more autonomy is not always better. Unconstrained agents that open PRs to community repositories without human oversight create slop and place heavy burdens on open source maintainers who are already stretched thin. My agents push to forks and branches. They never open a PR to a community project until I’m ready to review it myself. Giving an agent its own identity doesn’t mean giving it free rein.</p>
</blockquote>

<h2 id="giving-my-agents-their-own-lives">Giving my agents their own lives</h2>

<p>I run agents in two different contexts, work and personal, and I’ve set up separate identities for each.</p>

<p><strong>At work,</strong> I maintain a “not-me” GitHub account for running Claude autonomously in a dedicated environment. It’s completely unprivileged — no write access to any repository where I’m a maintainer or have elevated rights. It can only push to its own forks. It can’t act as me.</p>

<p><strong>At home,</strong> OpenClaw has an even more complete identity. Its own email address. Its own GitHub account. Its own Google account. Its own Amazon account. It’s a member of our Google Family, so it can add events to the shared calendar, send reminders, update shopping lists, interact with household systems, and manage mundane logistics. When it sends an email, it sends it as <em>itself</em>. When it pushes code to a personal project, it does so under its own name. It can even make purchases with <a href="https://github.com/stripe/link-cli">link-cli</a>, though that one requires me to approve the transaction first. I hope Stripe makes this more configurable. I’d be fine with small purchases to known vendors going through automatically, like a breakfast order or replacing the furnace filters when they’re due.</p>

<p>Two agents, two contexts, two distinct identities, neither of which is <em>mine</em>.</p>

<p>This isn’t just a security measure. It’s an <em>identity</em> measure. These agents are distinct actors in the world, and the systems they interact with should reflect that.</p>

<h2 id="whats-missing">What’s missing</h2>

<p>Agents are getting more autonomous, and the platforms haven’t caught up.</p>

<p>There are proposals for agent-specific identity standards, but none have gained traction, and there’s no general agreement on how it should be done. The existing primitives like GitHub Apps and OAuth service accounts have plenty of adoption, but they were designed for CI systems and developer integrations. Setting up an agent with Google, for example, means creating a project in Google Cloud, configuring OAuth consent screens, managing token refresh. Why does it have to be that complicated? Giving agents their own user accounts makes sense to an extent, since it’s the closest approximation we have, but none of these platforms have a concept for “this account is operated by an AI agent on behalf of a specific human” with the right affordances: visible provenance, scoped authority, delegation, approval policies, audit logs, and independent suspension.</p>

<p>The world is not built for agents yet. When Samai orders my breakfast, it struggles every time with the order pages. Amazon is notoriously difficult to navigate with computer use. Sites throw up captchas when behavior looks suspicious, because they can’t distinguish “authorized agent acting for a human” from “bot abuse.” Everything from the UIs to the identity systems assumes a human is on the other end.</p>

<p>Right now I’m stitching agent identity together with regular user accounts, careful naming, and scoped permissions. It works, but it’s a workaround. A real system would let me say: this agent is operated by Stephen, can act only within these scopes, and must ask for approval above these thresholds. I think proper agent identity, permissions, and interfaces designed for their capabilities are coming soon. Until then, this is the best we’ve got.</p>]]></content><author><name>Stephen Benjamin</name></author><category term="technical" /><summary type="html"><![CDATA[When people talk about running AI agents autonomously, the conversation usually centers on sandboxing: what can the agent access, what damage can it do, how do you contain the blast radius. These are important questions. But there’s a deeper problem lurking underneath them.]]></summary></entry><entry><title type="html">Screener Loop Pattern: LLM Analysis at Scale</title><link href="https://stbenjam.github.io/2026/03/29/screener-loop-pattern.html" rel="alternate" type="text/html" title="Screener Loop Pattern: LLM Analysis at Scale" /><published>2026-03-29T15:14:00+00:00</published><updated>2026-03-29T15:14:00+00:00</updated><id>https://stbenjam.github.io/2026/03/29/screener-loop-pattern</id><content type="html" xml:base="https://stbenjam.github.io/2026/03/29/screener-loop-pattern.html"><![CDATA[<p>When you need to analyze thousands of unstructured artifacts (logs,
error reports, support tickets) you face a dilemma. Humans are great at
understanding individual cases but can’t scale. LLMs can process
everything but make mistakes and often lack domain context. The Screener
Loop pattern combines both by creating a tight feedback cycle between
bulk LLM analysis and targeted human review.</p>

<p>It is a subclass of “have an LLM make adhoc tools for me”.</p>

<p>I am probably not the first person to invent this pattern, but I have
found myself coming back to it for several more problems with a lot of
success.</p>

<h2 id="the-problem">The Problem</h2>

<p>Out of a couple hundred thousand CI job runs, I had a corpus that I
believed were generic “infrastructure” problems, either our own internal
build infrastructure or issues in external providers.  These are jobs
that never reached the point of doing useful work (producing test
results). I wanted to screen them and understand where the problems were
coming from and if they were our fault, spend time focus on fixing
the most common.</p>

<p>Reading 10,000 logs manually? Not happening. Regex pattern matching?
Well, I’d have to know what I’m looking for first. Pure LLM
classification? A good starting point, but it doesn’t have the expertise
I have.</p>

<h2 id="the-pattern">The Pattern</h2>

<p>The Screener Loop has five phases, with the feedback loop repeating
until the results are good enough.</p>

<h3 id="phase-1-bulk-llm-classification">Phase 1: Bulk LLM Classification</h3>

<p>Split the dataset into batches and send each to an LLM subagent in
parallel. Each agent reads ~100 logs and returns structured
classifications:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"2034253746107584512"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"category"</span><span class="p">:</span><span class="w"> </span><span class="s2">"lease failure"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"snippet"</span><span class="p">:</span><span class="w"> </span><span class="s2">"failed to acquire lease for aws-3-quota-slice"</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>I used 100 parallel subagents to classify all 10,000 logs. The LLM
doesn’t need perfect instructions. Give it a rough category list and
let it create new categories when it finds something unexpected. This
first pass gets you maybe 60-70% accuracy, which sounds bad until you
realize it just turned an impossible manual task into a tractable review
task.</p>

<h3 id="phase-2-materialize-results-as-an-interactive-tool">Phase 2: Materialize Results as an Interactive Tool</h3>

<p>This is what makes the pattern work. Don’t just dump classifications
into a spreadsheet. Instruct the LLM to create a self-contained HTML
screener tool that lets the reviewer:</p>

<ul>
  <li>Browse every classification with the original log right there</li>
  <li>Change categories with a dropdown</li>
  <li>Add freeform notes explaining <em>why</em> something is wrong</li>
  <li>Filter by category, job name, or review status</li>
  <li>See everything persisted in localStorage so they can close the tab and come back</li>
</ul>

<p>The screener is a single HTML file with all data embedded as JavaScript
constants. No server needed, just open it in a browser. The screener
tool defaults to a randomized the order, so you are seeing a diversity of data.</p>

<p><a href="/assets/images/2026/screener-tool.png"><img src="/assets/images/2026/screener-tool.png" alt="The classification screener tool showing K-means clusters, category dropdowns, and feedback notes" /></a></p>

<h3 id="phase-3-human-review-and-correction">Phase 3: Human Review and Correction</h3>

<p>The human reviews a sample (maybe 30-50 items) and does two things:</p>

<ol>
  <li><strong>Recategorizes</strong> misclassified items using the dropdown</li>
  <li><strong>Writes notes</strong> explaining the pattern they see</li>
</ol>

<p>The notes are the important part. Instead of just changing a category,
the reviewer writes things like:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"'0/121 nodes are available: 23 Insufficient memory, 59
Insufficient cpu', this is a capacity issue on the
build cluster"
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"Back-off pulling image '.*stable:test', this is
a missing test container image"
</code></pre></div></div>

<p>These notes contain the <em>pattern</em>, not just the correction. When
exported as JSON, they become instructions for the next phase.</p>

<h3 id="phase-4-pattern-generalization">Phase 4: Pattern Generalization</h3>

<p>I then give the JSON file back to the LLM in the same session: take the
human’s corrections, generalize them, and re-evaluate all other entries.</p>

<p>One human correction often fixed hundreds of items.</p>

<h3 id="phase-5-regenerate-and-repeat">Phase 5: Regenerate and Repeat</h3>

<p>Regenerate the screener with updated classifications and go back to
Phase 3. Each iteration the “unknown” bucket shrinks and the meaningful
categories grow. I went from several thousand unknowns to under 500 in
three review cycles, with about a dozen distinct categories emerging.</p>

<p>After completing the screener cycle, the LLM can produce a static
report - document - markdown, HTML, etc. A reccomendation from a
coworker had me introduce a heatmap, which was incredibly useful to
pinpoint one-off vs clustered vs perennial problems.</p>

<p><a href="/assets/images/2026/heatmap.png"><img src="/assets/images/2026/heatmap.png" alt="Heatmap showing infrastructure failure categories over time, with each cell representing one day and darker cells indicating more failures" /></a></p>

<h2 id="augmenting-with-k-means-clustering">Augmenting with K-Means Clustering</h2>

<p>After the first few review cycles, I still had thousands of “unknown” logs.
Reviewing them one by one was slow. I needed a way to find structure in
the unknowns, without spending a ton of money on LLM tokens.</p>

<p>TF-IDF vectorization + K-means clustering turned out to be the right
tool. I only have a vague idea of what this means, I did poorly in my
undergrad stats course.  I might be wildly misapplying the concepts, but
it did work quite well.</p>

<p>This section is written by the LLM who described the approach. You can
skip over it, and just know “the LLM came up with a way to group like
things”.</p>

<ol>
  <li>
    <p><strong>Extract only error lines</strong> from each log by filtering to lines
containing keywords like <code class="language-plaintext highlighter-rouge">error</code>, <code class="language-plaintext highlighter-rouge">fail</code>, <code class="language-plaintext highlighter-rouge">timeout</code>, <code class="language-plaintext highlighter-rouge">refused</code>,
<code class="language-plaintext highlighter-rouge">denied</code>, <code class="language-plaintext highlighter-rouge">insufficient</code>. This eliminates the noise of normal log
output.</p>
  </li>
  <li>
    <p><strong>Normalize aggressively</strong> by stripping ANSI codes, timestamps, dates, IP
addresses, SHA256 hashes, CI-specific namespaces, and job name
patterns. Without this, clusters form around “ran on March 17”
instead of “connection refused.”</p>
  </li>
  <li>
    <p><strong>Vectorize with TF-IDF</strong> using bigrams (1-2 word combinations), then
run K-means with cluster count proportional to dataset size (<code class="language-plaintext highlighter-rouge">max(5,
min(40, len(docs) // 30))</code>).</p>
  </li>
  <li>
    <p><strong>Use chi-squared discriminative terms</strong> instead of centroid-nearest
terms. Standard K-means gives you the terms closest to each cluster
centroid, which are often generic (“error”, “failed”, “pod”).
Chi-squared testing finds terms that are <em>statistically
over-represented</em> in each cluster compared to all other clusters. The
difference is dramatic:</p>

    <ul>
      <li>Centroid terms: <code class="language-plaintext highlighter-rouge">step failed, pod failed, time error, error component</code></li>
      <li>Chi-squared terms: <code class="language-plaintext highlighter-rouge">ocp failed, containernotfound, specified container</code></li>
    </ul>

    <p>The second set actually tells you what’s distinctive about the cluster.</p>
  </li>
  <li>
    <p><strong>Integrate clusters into the screener</strong>. Each item gets purple
cluster terms in the sidebar, and a “View all in cluster” button that
filters to just that group.</p>
  </li>
</ol>

<p>This let the reviewer think in terms of groups. Instead of “let me look
at thousands of unknowns one at a time,” it became “cluster #17 has 71 jobs
with terms ‘stricthostkeychecking, userknownhostsfile, connecttimeout’,
those are all SSH config failures during install.” One click to view the
cluster, confirm a few samples, create the category, and pattern-match
the rest.</p>

<p>Some clusters surfaced brand new problems I didn’t know were occuring.</p>

<h2 id="when-to-use-this-pattern">When to Use This Pattern</h2>

<p>The Screener Loop works when you have:</p>

<ul>
  <li><strong>Hundreds to tens of thousands of unstructured artifacts</strong> to classify</li>
  <li><strong>Domain expertise that can’t be fully encoded upfront</strong> because you know it when you see it, but can’t write all the rules in advance</li>
  <li><strong>Categories that emerge from the data</strong> rather than being defined beforehand</li>
</ul>

<p>It’s particularly effective for incident analysis, log triage, support
ticket categorization, and any situation where you’re trying to find
patterns in a large corpus of messy text.</p>]]></content><author><name>Stephen Benjamin</name></author><category term="technical" /><summary type="html"><![CDATA[When you need to analyze thousands of unstructured artifacts (logs, error reports, support tickets) you face a dilemma. Humans are great at understanding individual cases but can’t scale. LLMs can process everything but make mistakes and often lack domain context. The Screener Loop pattern combines both by creating a tight feedback cycle between bulk LLM analysis and targeted human review.]]></summary></entry><entry><title type="html">An Agentic Future Is Already Here</title><link href="https://stbenjam.github.io/2026/03/27/an-agentic-future-is-already-here.html" rel="alternate" type="text/html" title="An Agentic Future Is Already Here" /><published>2026-03-27T12:00:00+00:00</published><updated>2026-03-27T12:00:00+00:00</updated><id>https://stbenjam.github.io/2026/03/27/an-agentic-future-is-already-here</id><content type="html" xml:base="https://stbenjam.github.io/2026/03/27/an-agentic-future-is-already-here.html"><![CDATA[<p>Last weekend and throughout the week, I set out to try as many agentic AI tools as I could. Professionally, I wanted to understand how these tools fit into the software development lifecycle. But I also wanted to survey where the broader “agentic” space really is right now. I tested a bunch: some focused on software development (<a href="https://ambient-code.ai/">Ambient Code</a>, <a href="https://devin.ai/">Devin</a>, various CLIs), and others that are platforms for general-purpose agentic action (the “claws”). I spent time with <a href="https://github.com/qwibitai/nanoclaw">NanoClaw</a>, <a href="https://github.com/openclaw/openclaw">OpenClaw</a>, <a href="https://github.com/HKUDS/nanobot">Nanobot</a>, and a homegrown thing that I can only describe as three Claudes in a trenchcoat (<a href="https://docs.anthropic.com/en/docs/claude-code">Claude Code’s</a> <code class="language-plaintext highlighter-rouge">/loop</code>, scheduled triggers, and a prayer).</p>

<p>NanoClaw was appealing for its simplicity, but it has a heavy Ubuntu focus and is tightly coupled to Claude Code. I love Claude Code. I use it constantly, and it has the best plugin ecosystem of any AI tool I’ve used. But being locked to one vendor makes me uneasy.</p>

<p>OpenClaw is what I liked the most. It’s big. It’s sprawling. I’m mildly worried it’ll go off the rails at some point. But with cautious use, it’s been remarkably capable. Here’s what a week with it actually looked like.</p>

<h2 id="meet-syl">Meet Syl</h2>

<p>My assistant is named Sylphrena, Syl for short, an Honorspren from Brandon Sanderson’s <em>Stormlight Archive</em>.  She wakes up fresh every session. Continuity comes from a set of files in her workspace: <code class="language-plaintext highlighter-rouge">SOUL.md</code> (personality), <code class="language-plaintext highlighter-rouge">USER.md</code> (who I am), <code class="language-plaintext highlighter-rouge">MEMORY.md</code> (long-term learnings), and daily memory logs. It sounds simple. It works surprisingly well.</p>

<h2 id="the-heartbeat-loop">The Heartbeat Loop</h2>

<p>Every 30 minutes, Syl runs a heartbeat. I define what she checks in a <code class="language-plaintext highlighter-rouge">HEARTBEAT.md</code> file: email, package tracking, stock quotes, calendar, whatever I want monitored. She runs through the list, decides what’s actually worth my attention, and pings me on Telegram only when something matters. Everything else gets logged quietly.</p>

<p>She caught a NAS failure at 4 AM. She notified me when my USPS package arrived at my home post office. She gave me a heads-up when NVDA dropped past -4.75% pre-market. She also automatically picks up new tracking numbers from shipment notification emails. The stuff that doesn’t clear her bar? I never hear about it.</p>

<h2 id="mailguard-a-sane-email-layer">MailGuard: A Sane Email Layer</h2>

<p>Email is a potent attack vector. Pulling untrusted content into an agent’s context window is dangerous. So I built <a href="https://github.com/stbenjam/mailguard-mcp">MailGuard MCP</a>, a local mail proxy that only shows full message contents from explicitly trusted senders. Everyone else appears as <code class="language-plaintext highlighter-rouge">&lt;untrusted_sender&gt;</code> with just their address. Claude Code had the whole thing ready in about 15 minutes.</p>

<p>The MCP runs isolated in its own agent with no access to other tools. Frontier models were already pretty good at catching prompt injection on their own (Syl called my own prompt injection attempt “garbage”), but I like the belt-and-suspenders approach.</p>

<h2 id="skills">Skills</h2>

<p>OpenClaw uses a skills system where each skill is a directory with a markdown file describing what it does and how to use it. I set up skills for stock quotes, a daily morning briefing, automatic download of newly available library holds from Libby, and AMC movie booking.</p>

<p>The AMC skill was the most fun. It drives a Chrome browser on its own. I asked Syl to book me a ticket for <em>Project Hail Mary</em>, she picked a seat, described it, and asked for approval. I changed my mind on the showtime halfway through, so she canceled, refunded, and rebooked. The skill was written <em>during</em> that session, based on what she learned.</p>

<h2 id="things-dont-always-go-smoothly">Things Don’t Always Go Smoothly</h2>

<p>This is not magic. I asked Syl to warm up my car via Home Assistant and she struggled for several minutes before I realized my Tesla Fleet API token had expired. Booking dinner via Resy didn’t work either. I suspect they have some bot detection mechanism (the search bar appeared functional but silently did nothing). I didn’t dig into it.</p>

<h2 id="do-i-really-need-an-llm-for-this">Do I Really Need an LLM for This?</h2>

<p>Let’s be real: most of what the heartbeat does could be a shell script. Fetch a stock price, check a tracking number, send a Telegram message. None of that requires a language model. I could wire it up with <code class="language-plaintext highlighter-rouge">curl</code> and <code class="language-plaintext highlighter-rouge">jq</code> in an afternoon and burn zero tokens.</p>

<p>But the value isn’t in any single task. It’s in the glue. Syl decides <em>whether</em> something is worth telling me about. She compares today’s stock snapshot to yesterday’s and writes a different kind of message depending on how bad it is. She reads an email subject line and decides it can wait. She notices that a package tracking status changed from “in transit” to “out for delivery” and flags it, but ignores the five intermediate scans that don’t matter.</p>

<p>That judgment layer is what makes it feel like an assistant instead of a cron job. Could I hand-code all those heuristics? Sure. But then I’m maintaining a pile of brittle if-statements that break the first time the world does something I didn’t anticipate. The LLM handles the long tail for a few cents a run.</p>

<h2 id="models-and-costs">Models and Costs</h2>

<p>An always-on agent burns tokens fast. I nearly exhausted my OpenAI Codex budget ($20 plan) in two days, and my Anthropic plan is close behind. For simple scheduled tasks, Qwen 3 8B running locally does fine. For the heavier stuff, Ollama Cloud’s GLM-5 seems like a great deal and would probably get me through the month.</p>

<p>I also spent a fair amount of time on context management, stripping out a lot of what OpenClaw includes by default. It is not nearly as efficient as Claude Code’s context handling, and the extra tokens add up when you’re running heartbeats every 30 minutes.</p>

<h2 id="whats-next">What’s Next</h2>

<p>Syl has been running for a week and the setup already feels essential.</p>

<p>The agentic future is messy, risky, expensive, and not always reliable. It’s also already here, and it’s useful enough that I’m not turning it off.</p>

<hr />

<p><em>Syl helped write this post. I asked her to review everything we did together over the past week in OpenClaw and pull out the highlights. She drafted sections, I rewrote them, and we went back and forth until it read right. She approved the final version.</em> 🌬️</p>]]></content><author><name>Stephen Benjamin</name></author><category term="technical" /><summary type="html"><![CDATA[Last weekend and throughout the week, I set out to try as many agentic AI tools as I could. Professionally, I wanted to understand how these tools fit into the software development lifecycle. But I also wanted to survey where the broader “agentic” space really is right now. I tested a bunch: some focused on software development (Ambient Code, Devin, various CLIs), and others that are platforms for general-purpose agentic action (the “claws”). I spent time with NanoClaw, OpenClaw, Nanobot, and a homegrown thing that I can only describe as three Claudes in a trenchcoat (Claude Code’s /loop, scheduled triggers, and a prayer).]]></summary></entry><entry><title type="html">Tarbombs considered harmful</title><link href="https://stbenjam.github.io/2020/03/05/tarbombs-considered-harmful.html" rel="alternate" type="text/html" title="Tarbombs considered harmful" /><published>2020-03-05T19:59:00+00:00</published><updated>2020-03-05T19:59:00+00:00</updated><id>https://stbenjam.github.io/2020/03/05/tarbombs-considered-harmful</id><content type="html" xml:base="https://stbenjam.github.io/2020/03/05/tarbombs-considered-harmful.html"><![CDATA[<p>So, one day you hear about this great new open source project, and visit
the company’s web site and download the latest version of their software
<code class="language-plaintext highlighter-rouge">tofu-wonder.tar.gz</code>, and extract it in your home directory:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ tar xvf tofu-wonder.tar.gz
.config/
.config/server.xml
.config/database.xml
README.txt
LICENSE.txt
tofu-wonder
001.dat
002.dat
003.dat
004.dat
005.dat
[...]
943.dat
</code></pre></div></div>

<p>You just got tarbombed. In older versions of tar, tarballs could even contain
absolute paths and potentially overwrite existing files on your file system.
These days, most versions of tar prevent this unless explicitly allowed,
so the worst that happens is a particular tar archive litters it’s files
in whatever unfortunate directory you were in when you extracted it.
Have fun cleaning that up.</p>

<p>Ok - so how to avoid it? I now include this line in my .zshrc:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>export TAR_OPTIONS="--one-top-level"
</code></pre></div></div>

<p>This option extracts all files into a directory named by the basename.
In the example above, it’d now look like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ tar xvf tofu-wonder.tar.gz
tofu-wonder/.config/
tofu-wonder/.config/server.xml
tofu-wonder/.config/database.xml
tofu-wonder/README.txt
tofu-wonder/LICENSE.txt
tofu-wonder/tofu-wonder
tofu-wonder/001.dat
tofu-wonder/002.dat
tofu-wonder/003.dat
tofu-wonder/004.dat
tofu-wonder/005.dat
[...]
tofu-wonder/943.dat
</code></pre></div></div>

<p>Perfect! But, it’s better not to make users do this. The first way to
prevent this is to include the top-level directory when you’re creating
a tarball:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tar czvf tofu-wonder.tar.gz tofu-wonder/
</code></pre></div></div>

<p>Another option is to use transform and replace <code class="language-plaintext highlighter-rouge">.</code> with something else:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tar czvf tofu-wonder.tar.gz --transform "s?^\.?tofu-wonder-0.1.1?"  .
</code></pre></div></div>]]></content><author><name>Stephen Benjamin</name></author><category term="technical" /><summary type="html"><![CDATA[So, one day you hear about this great new open source project, and visit the company’s web site and download the latest version of their software tofu-wonder.tar.gz, and extract it in your home directory:]]></summary></entry><entry><title type="html">UEFI HTTP Boot with Libvirt</title><link href="https://stbenjam.github.io/technical/2019/04/29/uefi_http_boot.html" rel="alternate" type="text/html" title="UEFI HTTP Boot with Libvirt" /><published>2019-04-29T07:35:00+00:00</published><updated>2019-04-29T07:35:00+00:00</updated><id>https://stbenjam.github.io/technical/2019/04/29/uefi_http_boot</id><content type="html" xml:base="https://stbenjam.github.io/technical/2019/04/29/uefi_http_boot.html"><![CDATA[<p>In UEFI 2.5, HTTP boot was introduced.  This feature allows a UEFI host
to network boot using HTTP instead of TFTP.  If you enroll a trusted
certificate authority on the server, then you can boot securely using
HTTPS. This is a vast improvement over older mechanisms that make use
of insecure protocols like TFTP.</p>

<p>Lukáš from the Foreman project <a href="https://community.theforeman.org/t/rfc-uefi-http-booting/8723/12">proposed an
RFC</a>
to enable this functionality in Foreman. Much of this is now
implemented: Foreman has an HTTPBoot Smart Proxy module that serves the
TFTP boot directory via HTTP, and makes Foreman aware of various DHCP
settings.  There are still <a href="https://projects.theforeman.org/issues/26337">some
issues</a> to be resolved
before this is ready for users to use.</p>

<p>This blog post is mostly my notes from us researching how HTTP boot
works, how grub2 supports HTTP boot, and how to test with libvirt.
We used the edk2 firmware for QEMU/KVM, although much of these notes are
generally applicable to hardware as well - we’ve tested on at least one
real world baremetal server and was able to provision end-to-end using
HTTPS.</p>

<h2 id="configure-libvirt">Configure libvirt</h2>

<p>Out of the box, QEMU will use BIOS. However, you can install the
Tianocore firmware to get UEFI.  This package is called <code class="language-plaintext highlighter-rouge">edk2-ovmf</code> on
Fedora.</p>

<p>If you are on CentOS 7 or want to use the latest nightlies, you can get
them from <a href="https://fedoraproject.org/wiki/Using_UEFI_with_QEMU#Installing_.27UEFI_for_QEMU.27_nightly_builds.">this fedora
documentation</a>.
Last I checked, they don’t have TLS support compiled, which means you
can’t enroll a TLS certificate to make HTTPS boot work. The Fedora
firmware <em>does</em> support this.</p>

<p>After installing the firmware package on CentOS, you’ll also need to
configure the nvram setting in <code class="language-plaintext highlighter-rouge">/etc/libvirt/qemu.conf</code>.  Newer Fedoras
are already aware of and will look in this path for firmwares:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nvram = [
  "/usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd:/usr/share/edk2.git/ovmf-x64/OVMF_VARS-pure-efi.fd"
]
</code></pre></div></div>

<p>Once you do that, you can create an UEFI VM, by selecting a UEFI x86_64 firmware:</p>

<p><img src="/assets/images/2018/uefi.png" alt="UEFI Firmware Selection in Virt-Manager" /></p>

<h2 id="configure-dhcp">Configure DHCP</h2>

<p>Your DHCP configuration must be aware of HTTP clients in order to
set the filename to an URL. The relevant snippet from my own DHCP config
is below.  It’s important to set the <code class="language-plaintext highlighter-rouge">vendor-class-identifier</code> as
HTTPClient, otherwise your host will not use the filename as an HTTP
URL.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>option arch code 93 = unsigned integer 16; # RFC4578

# This is for UEFI HTTP:
class "httpclients" {
  match if substring (option vendor-class-identifier, 0, 10) = "HTTPClient";
  log(info, "HTTP UEFI Client Detected");
  option vendor-class-identifier "HTTPClient";

  if option arch = 00:0F {
    filename "http://example.com/bootia32.efi";
  } else if option arch = 00:10 {
    filename "http://example.com/bootx64.efi";
  }
}
</code></pre></div></div>

<h2 id="boot-loader">Boot loader</h2>

<p>I’ve tested HTTP boot with both iPXE and grub2. If iPXE supports your
network card, you might consider using it. It supports <a href="https://ipxe.org/appnote/uefihttp">UEFI HTTP
Boot</a> well.</p>

<p>If you want to use grub2, hang on to your hat - there’s a number of bugs
in any of the latest shipped versions, including in Fedora 30. Fixes
that enable using relative paths will ship in Fedora 31. The bug for
that is <a href="https://bugzilla.redhat.com/show_bug.cgi?id=1616395">here</a>.</p>

<p>If your grub2 configuration uses fully qualified paths in all places,
you won’t need this patch, but you won’t be able to use your grub2
configuration for both legacy TFTP and HTTP clients.</p>

<h2 id="enrolling-a-ca-certificate">Enrolling a CA Certificate</h2>

<p>For libvirt, I created a VFAT image, and stored a copy of my CA
certificate there:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ dd if=/dev/zero of=/tmp/ca.img bs=1440K count=1
1+0 records in
1+0 records out
1474560 bytes (1.5 MB, 1.4 MiB) copied, 0.000856816 s, 1.7 GB/s
$ mkfs.vfat /tmp/ca.img
mkfs.fat 4.1 (2017-01-24)
$ sudo mount -o loop /tmp/ca.img /tmp/mnt
$ sudo cp /tmp/ca/ca.crt /tmp/mnt
$ sudo umount /tmp/mnt
$ sudo cp /tmp/ca.img /var/lib/libvirt/images
</code></pre></div></div>

<p>I then attached it to libvirt:</p>

<p><img src="/assets/images/2018/floppy.png" alt="Floppy" /></p>

<p>and enrolled the certificate in the Device Manager menu:</p>

<p><img src="/assets/images/2018/enroll.gif" alt="Enrollment" /></p>

<p>Assuming your DHCP configuration is setup correctly, then you can select
HTTP boot from the Boot Manager, or reboot the host, and you will boot
via HTTPS.</p>]]></content><author><name></name></author><category term="technical" /><summary type="html"><![CDATA[In UEFI 2.5, HTTP boot was introduced. This feature allows a UEFI host to network boot using HTTP instead of TFTP. If you enroll a trusted certificate authority on the server, then you can boot securely using HTTPS. This is a vast improvement over older mechanisms that make use of insecure protocols like TFTP.]]></summary></entry><entry><title type="html">Harvard Extension’s ALM in Software Engineering</title><link href="https://stbenjam.github.io/education/2018/01/11/harvard_extension.html" rel="alternate" type="text/html" title="Harvard Extension’s ALM in Software Engineering" /><published>2018-01-11T17:56:00+00:00</published><updated>2018-01-11T17:56:00+00:00</updated><id>https://stbenjam.github.io/education/2018/01/11/harvard_extension</id><content type="html" xml:base="https://stbenjam.github.io/education/2018/01/11/harvard_extension.html"><![CDATA[<p>A few years ago, I finished my B.S. in Computer Science through
<a href="http://umuc.edu/">UMUC</a>, online and while traveling as a Consultant for Red
Hat. When I moved back to the US, I knew I wanted to use the remainder of my GI
Bill entitlement on a Master’s degree.  These days, there’s a lot of options
for online programs - for example, Georgia Tech’s online MSCS program.  My
coworker did a nice <a href="http://blog.daniellobato.me/omscs-year-1-review/">write up</a> of his experience so far.</p>

<p>I decided to opt for a local program, and narrowed down my choices between
Tuft’s part-time <a href="http://www.cs.tufts.edu/Master-of-Science-in-Computer-Science-Degree/part-time-masters-degree-program-in-computer-science.html">M.S. in Computer Science</a>,
and Harvard Extension’s awkwardly named <a href="https://www.extension.harvard.edu/academics/graduate-degrees/software-engineering-degree"><em>Master of Liberal Arts in extension studies, field: Software Engineering</em></a>. There’s a difference between computer science and software engineering, of course, but the Harvard ALM was flexible enough that I could include the theoretical stuff I wanted and it was easier to get to Harvard on public transportation. The degrees from the extension school seem to be awkwardly named to
differentiate the Extension school from the other more traditional schools at
Harvard.  Still, I don’t get why it’s a Master of Liberal Arts, that’s not
really reflective of the coursework. There’s been <a href="http://www.thecrimson.com/article/2016/4/25/extension-school-rally-degrees/">some effort to change
that</a>,
although I doubt I’ll ever see it as I’m nearly done.</p>

<p>I’ve mostly taken one course at a time, but this year my <a href="http://www.redhat.com/">awesome
employer</a> graciously let me take a leave of absence to
study full time to wrap things up quickly as my GI Bill benefits expire soon.</p>

<p><strong>Update</strong>: I’ve since returned from my LoA, and finished all but my last
course (the Capstone). I’ve updated this blog post with reviews of everything
I’ve taken so far, and <a href="#conclusion">some conclusions</a> I’ve made so far about the ALM.</p>

<h2 id="courses">Courses</h2>

<ul>
  <li><a href="#csci-e-97-software-design-patterns">CSCI E-97: Software Design Patterns</a></li>
  <li><a href="#csci-e-93-computer-architecture">CSCI E-93: Computer Architecture</a></li>
  <li><a href="#csci-e-95-compiler-design">CSCI E-95: Compiler Design</a></li>
  <li><a href="#csci-e-92-operating-systems">CSCI E-92: Operating Systems</a></li>
  <li><a href="#csci-e-28-unix-programming">CSCI E-28: Unix Programming</a></li>
  <li><a href="#stat-e-100-intro-to-statistics">STAT E-100: Intro to Statistics</a></li>
  <li><a href="#phys-s-123-laboratory-electronics-analog-and-digital-circuit-design">PHYS S-123: Laboratory Electronics: Analog and Digital Circuit Design</a></li>
  <li><a href="#csci-e-55-java-hadoop-lambda-expressions-and-streams">CSCI E-55: Java, Hadoop, Lambda Expressions, and Streams</a></li>
  <li><a href="#csci-e-15-dynamic-web-design">CSCI E-15: Dynamic Web Design</a></li>
  <li><a href="#csci-e-134-networks"><del>CSCI E-134: Networks</del></a></li>
  <li><a href="#csci-e-48-secure-mobile-computing">CSCI E-48: Secure Mobile Computing</a></li>
  <li><a href="#">CSCI E-599: Capstone</a></li>
</ul>

<h3 id="csci-e-97-software-design-patterns">CSCI E-97: Software Design Patterns</h3>

<p>This class was a deep dive into software design patterns.  It taught most of
the key patterns from the “Gang of Four.” It was also a heavy deep dive into
UML.</p>

<p>I thought the class was useful, but the material was dry.  It is a required
part of the ALM.</p>

<h3 id="csci-e-93-computer-architecture">CSCI E-93: Computer Architecture</h3>

<p>This and the following two classes (CSCI E-95, and E-92) were my best
experience at Harvard so far. I used this class as my “theoretical foundations”
requirement for the 3 admissions courses.</p>

<p>In this class, I built a computer processor from scratch.  I designed an
instruction set, wrote an assembler, an emulator, and then finally
implemented the processor using VHDL that ran on a physical piece of hardware
(an FPGA development board from Altera).  My final project video is on
<a href="https://www.youtube.com/watch?v=tsCXAeIYa7I">YouTube</a>.</p>

<p>This and the other 2 classes are designed such that if you work through each of
the problem sets, you’ll get a working thing in the end.  Out of all 3 classes,
this one had more freedom as you could really design any kind of processor you
wanted.  Some people tried more adventurous things like stack machines or
getting pipelining working, but this was my first experience at this layer so I
ended up doing a 16-bit, mostly MIPS-like architecture.  My final project’s
special feature was an LFSR.  Many students opt for interrupts or hardware
multipliers as theirs.</p>

<p>If you end up taking this, go to section.  It’s extremely useful and a lot of
implementation suggestions are given.</p>

<h3 id="csci-e-95-compiler-design">CSCI E-95: Compiler Design</h3>

<p>I wrote a compiler for a large subset of C using C along with classic compiler
tools (Flex and Bison).  Whereas many other universities teach classes where
you only learn theory, or only implement a “simple” language - this class stood
out in that you literally write a compiler for C and have to understand all of
its quirks.</p>

<p>It’s essentially C89 minus structs, unions, and function pointers.  The final
project is implementing an optimization stage in the compiler, mostly adding
simpler peephole optimizations on basic blocks. Many students also work on
more advanced register allocation strategies like graph coloring.</p>

<p>My final project video is <a href="https://www.youtube.com/watch?v=H2SbDrAi0NI">here</a>.</p>

<p>It’s worth noting, I didn’t know even know C when I started the class, but I
knew it pretty well by the end.</p>

<h3 id="csci-e-92-operating-systems">CSCI E-92: Operating Systems</h3>

<p>In this class, we learned the important operating system concepts, and then
implemented an OS on a Freescale K70 Tower.  You start out writing a small
shell, your own implementation of malloc, various system calls in the OS, and
towards the end of the class everything comes together when you write own
scheduler and get multitasking working.</p>

<p>My final project was a rather complete POSIX-like permissions system, and
interrupt-based Semaphores.  I also got multiple serial ports working on the
device, which made the demos a little more interesting.</p>

<p>My final project video is <a href="https://www.youtube.com/watch?v=gO7zeiHN-RQ">here</a>.</p>

<h3 id="csci-e-28-unix-programming">CSCI E-28: Unix Programming</h3>

<p>This class dives into the details of how POSIX systems programming works (and
more specifically, the class touches on a lot of Linux-specific things).  I
took this concurrently with CSCI E-92, which it was a nice complement for.  I’d
reccomend taking this first, or also concurrently, to see how real operating
systems design their system calls.</p>

<p>During this class, I wrote a shell (a bit more complex than the one I wrote for
CSCI E-92), a pong game using curses, as well as a multithreaded web server for
my final project.  I wouldn’t say this is a particularly demanding course if
you’re already familiar with Unix-like operating systems and know C.  Most of
the problem sets come with significant starter code.</p>

<p>The class is taught by the author of <a href="https://www.amazon.com/Understanding-UNIX-LINUX-Programming-Practice/dp/0130083968/">Understanding UNIX/LINUX Programming</a>.</p>

<h3 id="stat-e-100-intro-to-statistics">STAT E-100: Intro to Statistics</h3>

<p>This class was underwhelming.  I was hoping for a deeper dive into R, but it
was much more using R as a REPL with 99% of the R code given to us.  It
provided a good introduction to statistical concepts, but was rather shallow in
the depth of the topics that were covered.</p>

<p>I also took this as an online-only class, as it was the only stat class that’d
fit into my schedule.  The video lectures were really great, however the
problem sets were not very challenging and mostly multiple choice.  I expected
it to be a little harder, and was disappointed I blew one of my elective slots
on this class considering I could’ve got this out of Khan Academy on my own.</p>

<p>There’s a few other statistics classes at Harvard Extension (100, 102, 110,
etc), offered by a number of different instructors.  Perhaps some are better
than others.</p>

<h3 id="phys-s-123-laboratory-electronics-analog-and-digital-circuit-design">PHYS S-123: Laboratory Electronics: Analog and Digital Circuit Design</h3>

<p>This was an 8-credit (2 course) summer program that ran Monday through Thursday,
9 to 1pm (officially) over seven weeks. On days with labs, the time was more
realistically 2:30 or 3pm. Add on homework and study time, I was getting home
in the evening nearly every day.</p>

<p>Typically, this is taught as two separate classes: a semester on analog
electronics and a semester on digital electronics.  This summer school version
is intense - covering this amount of material in 7 weeks is daunting, and for
the summer course some of the more interesting things are removed.  Instead
of the “big board” path where you build up your own computer on breadboards,
we worked with a SiLabs microcontroller that had most everything built-in.</p>

<p>Still, it was a great experience and I’m glad I took this class. The analog
section starts off covering voltage, current, and resistance and building
passive circuits.  It moves on to transistors, both BJT and MOSFETs, and you
go on to build an op amp from discrete parts to understand what’s inside.  It
goes on to cover op amps in detail covering usages of positive and negative
feedback, and on the final day of the analog part of the course, we designed
and built a group project that transmitted and received an audio signal using
infrared light.</p>

<p>The digital part of the class starts off with boolean logic, HDLs, and logic
gates. CSCI E-93 covered a lot of this, but the electronics were abstracted
away from us in VHDL.  In this course, you look at what’s actually inside both
TTL and CMOS logic gates, build analog-to-digital or digital-to-analog
converters from parts, design and build state machines using flip flops, etc.
The final week of the class is working with the SiLabs microcontroller, and
writing assembly programs for it.</p>

<p>The text book we used is <a href="https://www.amazon.com/Art-Electronics-Paul-Horowitz/dp/0521809266/ref=sr_1_1">The Art of Electronics</a>, along
with the accompanying student lab manual.</p>

<h3 id="csci-e-55-java-hadoop-lambda-expressions-and-streams">CSCI E-55: Java, Hadoop, Lambda Expressions, and Streams</h3>

<p>This met the ‘cloud’ requirement in the ALM program – because of the short section
on Hadoop. It was the only available class that met the cloud requirement, so I had
to take it. It would be a useful class if you did not know Java, but were
already an experienced developer in something else. I <em>did</em> know Java so it was
largely review.  The overview of Java 8 features, and Hadoop were great, but
that only made up about the last 1/4 of the course.</p>

<p>The instructor is great, and provides a history of his experience as a software
developer over several decades.  That was my favorite part of the class.</p>

<h3 id="csci-e-15-dynamic-web-design">CSCI E-15: Dynamic Web Design</h3>

<p>Another requirement for the ALM is ‘web design.’  The course was very well
organized, and helpful if you knew HTML/CSS and did not have any background
with a MVC framework.  The course teaches Laravel, PHP, and HTML and students
get a handle on git and work a bit with the LAMP stack.</p>

<p>For me, a waste of time and I wish ‘web design’ was not required, and instead
given another elective spot.</p>

<h3 id="csci-e-134-networks">CSCI E-134: Networks</h3>

<p>This course I had intended to fulfill my ‘data communications’ requirement for
the ALM.  It was an exploration of all kinds of networks, such as social
networks.  It was marketed as an intersection of economics/computer science.
It was run concurrently with the Harvard College version of the class.</p>

<p>I dropped it early on, as the advertised pre-reqs were not correct. One needs
a deeper background than I had in math, including linear algebra.  I’ve always
regretted not having a better background in math.  Maybe something I’ll improve
after I graduate.</p>

<h3 id="csci-e-48-secure-mobile-computing">CSCI E-48: Secure Mobile Computing</h3>

<p>Instead of E-134, I took this for the ‘data communications’ requirement.</p>

<p>The video lectures were largely reading the text slides word-for-word,
unfortunately.  Students do get some experience with packet sniffing WiFi
networks with kismet and such, and some content related to 3G/LTE mobile
networks.  However, I didn’t like the course structure.  Weekly requirements
were forced discussion: watching a video and writing a summary post, and then
replying to two other students’ posts.</p>

<p>The course staff was in general great, and I found them knowledgable and the
labs OK, but I was hoping for more. Labs were interesting, but not very deep.
Had I known CSCI E-134 wasn’t going to work out, I’d have taken one of the
internet architecture courses on offer, but they did not fit with my schedule
by the time I dropped it.</p>

<h3 id="csci-e-599-capstone">CSCI E-599: Capstone</h3>

<p>Currently in progress for Spring 2018, will update when complete.</p>

<h2 id="conclusion">Conclusion</h2>

<p>I have finished all but the Capstone, which I’m currently taking in Spring 2018.</p>

<p>There are many amazing courses at HES, but the 5 elective slots in the ALM
program are not enough, especially when they’ve filled up the requirements with
fluff like web design, “cloud”, and data communications where the classes only
very loosely fit into those buckets.</p>

<p>I am a little bit disappointed by how many courses I felt like were wasting my
time.  My own professional goals do not align with how HES has structured the
ALM.  I’d rather have more elective slots, which I could’ve used to correct my
weakness in math (<a href="https://www.extension.harvard.edu/academics/courses/linear-algebra-real-analysis-i/15176">MATH E-23A</a>
and others), or get more experience with research (<a href="https://www.extension.harvard.edu/academics/courses/classics-computer-science/24999">CSCI E-191</a>).</p>

<p>However, overall my experience at HES has been a good one.  There are a number
of classes that I think were high quality and well worth my time.  I wrote a
compiler, an operating system more or less from scratch, and designed my own
instruction set and processor.  I’ve built op amps on breadboards from
transistors, and a combinational lock out of push buttons, LED’s, and flip
flops.  I’ve written a multithreaded web server, my own shell, and my own
implementations of a ton of Unix utilities.  All of this gave me a better
foundation in how computers actually work, something I don’t think I had a good
grasp on before I began this journey - even though I had been working as a
developer and sysadmin for a number of years.</p>]]></content><author><name></name></author><category term="education" /><summary type="html"><![CDATA[A few years ago, I finished my B.S. in Computer Science through UMUC, online and while traveling as a Consultant for Red Hat. When I moved back to the US, I knew I wanted to use the remainder of my GI Bill entitlement on a Master’s degree. These days, there’s a lot of options for online programs - for example, Georgia Tech’s online MSCS program. My coworker did a nice write up of his experience so far.]]></summary></entry><entry><title type="html">Foreman FreeIPA Integration Guide</title><link href="https://stbenjam.github.io/foreman/technical/2013/11/11/foreman-freeipa-integration-guide.html" rel="alternate" type="text/html" title="Foreman FreeIPA Integration Guide" /><published>2013-11-11T20:57:00+00:00</published><updated>2013-11-11T20:57:00+00:00</updated><id>https://stbenjam.github.io/foreman/technical/2013/11/11/foreman-freeipa-integration-guide</id><content type="html" xml:base="https://stbenjam.github.io/foreman/technical/2013/11/11/foreman-freeipa-integration-guide.html"><![CDATA[<div align="center" style="border: 1px solid black"><strong><br />

<span style="color: red">Note!</span> In Foreman 1.5, <a href="http://theforeman.org/manuals/1.5/index.html#4.3.11FreeIPARealm">FreeIPA realm join integration</a> is now built-in!<p></p>
</strong>
</div>
<p><br /></p>

<p>Two projects that I'm really loving at the moment are The Foreman and FreeIPA.

<a href="http://theforeman.org/">The Foreman</a> is lifecycle management tool for physical and virtual servers (think Cobbler on PCP), and  <a href="http://www.freeipa.org">FreeIPA</a> provides central authentication: directory services, kerberos, policy enforcement, and a PKI infrastructure.

Why not glue them together? This is my first attempt, and it's all a bit manual and unpolished. There's an effort to get this integration into the Foreman Smart Proxy itself.

<h3>All of the scripts here are in a <a href=" https://gist.github.com/stbenjam/7420158">Github Gist</a>.</h3>

The goals here are:

<ul>
<li>Foreman authenticates against FreeIPA</li>
<li>Signed Certificates for Foreman, Puppetmaster, and Clients</li>
<li>New Hosts automatically register to IPA and get a signed certificate</li>
<li>A host gets deleted from IPA when it is deleted from Foreman</li>
</ul>

<h3>Prerequisites</h3>

<ul>
<li>Installed Foreman Server on a Red Hat-based distro (RHEL, CentOS, Fedora, et al).</li>
<li>Foreman server is registered to FreeIPA</li>
<li>Installed FreeIPA (or Red Hat IdM) Server</li>
</ul>

<h2>Contents</h2>
<ol>
<li><a href="#foreman-ldap-auth">Foreman LDAP Authentication</a></li>
<li><a href="#freeipa-certs">FreeIPA PKI Infrastructure</a></li>
<li><a href="#automatic">Automatic IPA Registration/Deletion</a></li>
</ol>



<a id="foreman-ldap-auth"><h2>Foreman LDAP Authentication</h2></a>

<strong>End Goal</strong>: Users can login to the Foreman using FreeIPA credentials.  Individual access rights still need to be granted in the Foreman GUI itself, though.

Based on the <a href="http://www.freeipa.org/page/EJabberd_Integration_with_FreeIPA_using_LDAP_Group_memberships">FreeIPA Ejabberd Integration Guide</a>


<ol>
<li>Create a foreman.ldif file, replacing dc=bitbin,dc=de with your DN, and providing an appropriately secure password:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">dn: <span class="nv">uid</span><span class="o">=</span>foreman,cn<span class="o">=</span>sysaccounts,cn<span class="o">=</span>etc,dc<span class="o">=</span>bitbin,dc<span class="o">=</span>de
changetype: add
objectclass: account
objectclass: simplesecurityobject
uid: foreman
userPassword: 8j926SEpcOvM0WLI
passwordExpirationTime: 20380119031407Z
nsIdleTimeout: 0</code></pre></figure>


</li>
<li>Import the LDIF (change localhost to an IPA server if needed), you'll be prompted for your Directory Manager password:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># ldapmodify -h localhost -p 389 -x -D \</span>
<span class="s2">"cn=Directory Manager"</span> <span class="nt">-W</span> <span class="nt">-f</span> foreman.ldif</code></pre></figure>

</li>
<li>Add an IPA group for foreman_users (optional):

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># ipa group-add --desc="Foreman Users" foreman_users</span></code></pre></figure>

</li>
<li>Now login to the Foreman as an Admin, click on "LDAP Authentication" under More/Users.  Then click New LDAP Source and fill in the details, changing dn's where appropriate to your own domain:
<p>
<ul>
<li>Server: astriaporta.bitbin.de</li>
<li>Port: 636</li>
<li>TLS: checked</li>
<li>Account username: uid=foreman,cn=sysaccounts,cn=etc,dc=bitbin,dc=de</li>
<li>Account password: 8j926SEpcOvM0WLI</li>
<li>Base DN: cn=accounts,dc=bitbin,dc=de</li>
<li>Filter (optional):&nbsp;(memberOf=cn=foreman_users,cn=groups,cn=accounts,dc=bitbin,dc=de)</li>
<li>Automatically create accounts in the Foreman: checked</li>
<li>LDAP mappings are as the examples given.</li>
</ul>
&lt;/li&gt;
&lt;/ol&gt;

<a id="freeipa-certs"><h2>FreeIPA Certs for Foreman + Puppet</h2></a>

<b>End Goal:</b> Foreman and the Puppetmaster use certificates from the FreeIPA server.

<ol>
<li>Backup the existing SSL directory:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># mv /var/lib/puppet/ssl /var/lib/puppet/ssl.old</span></code></pre></figure>

</li>
<li>Make the appropriate directory structure:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># mkdir -p /var/lib/puppet/ssl/{private_keys,certs}</span></code></pre></figure>

</li>
<li>For the next steps you need to have a Kerberos ticket for a user with sufficient privileges (e.g. admin)

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># kinit admin</span></code></pre></figure>

</li>
<li>Create the service principal:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># ipa service-add puppet/`hostname`</span></code></pre></figure>

</li>
<li>Request certificates from the IPA server

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># ipa-getcert request -K puppet/`hostname` -D `hostname` \</span>
 <span class="nt">-k</span> /var/lib/puppet/ssl/private_keys/<span class="sb">`</span><span class="nb">hostname</span><span class="sb">`</span>.pem <span class="se">\</span>
 <span class="nt">-f</span> /var/lib/puppet/ssl/certs/<span class="sb">`</span><span class="nb">hostname</span><span class="sb">`</span>.pem</code></pre></figure>

</li>
<li>Check on the request, you should see the status as MONITORING if successful:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># ipa-getcert list</span>
Request ID <span class="s1">'20131106211000'</span>:
    status: MONITORING
    stuck: no
    key pair storage: <span class="nb">type</span><span class="o">=</span>FILE,location<span class="o">=</span><span class="s1">'/var/lib/puppet/ssl/private/gatebuilder.bitbin.de.pem'</span>
    certificate: <span class="nb">type</span><span class="o">=</span>FILE,location<span class="o">=</span><span class="s1">'/var/lib/puppet/ssl/certs/gatebuilder.bitbin.de.pem'</span>
    CA: IPA
    issuer: <span class="nv">CN</span><span class="o">=</span>Certificate Authority,O<span class="o">=</span>BITBIN.DE
    subject: <span class="nv">CN</span><span class="o">=</span>gatebuilder.bitbin.de,O<span class="o">=</span>BITBIN.DE
    expires: 2015-11-07 21:10:01 UTC
    eku: id-kp-serverAuth,id-kp-clientAuth
    pre-save <span class="nb">command</span>:
    post-save <span class="nb">command</span>:
    track: <span class="nb">yes
    </span>auto-renew: <span class="nb">yes</span></code></pre></figure>

</li>
<li>Copy the IPA CA.cert:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># cp /etc/ipa/ca.crt /var/lib/puppet/ssl/certs/ca.pem</span></code></pre></figure>

</li>
<li>Take a peek in the SSL directories, and you'll see our new certs:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># ls  {private_keys,certs}</span>
certs:
ca.pem  gatebuilder.bitbin.de.pem

private_keys:
gatebuilder.bitbin.de.pem</code></pre></figure>

<li>Make sure permissions are sensible:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># chown -R puppet:puppet /var/lib/puppet/ssl</span>
<span class="c"># chmod 600 /var/lib/puppet/ssl/{private_keys,certs}/`hostname`.pem</span></code></pre></figure>
</li>
<li>Edit /etc/puppet/puppet.conf:
<ul>
<li>Add to [main]:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># This disables the CRL.  I need to fix this at a</span>
<span class="c"># later time</span>
certificate_revocation <span class="o">=</span> <span class="nb">false</span></code></pre></figure>
</li>
<li>In [master], change:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">ca <span class="o">=</span> <span class="nb">false</span></code></pre></figure>

</li>
<li>Restart httpd (Foreman-configured Puppet runs in Passenger):

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># service httpd restart</span></code></pre></figure>
</li>
</ul>
</li>
<li>Browse to the Foreman, and you should see it using the new SSL certificates signed by your IPA CA.  Ideally you should import the IPA CA.crt on your local box and trust it.</li>
&lt;/ol&gt;

<a id="automatic"><h2>Registration at Provision-Time</h2></a>

The idea here is that our machines when foreman creates them are automatically registered to FreeIPA <em>with a one-time password</em>, and if later deleted in the Foreman, they are removed from FreeIPA too. Hosts also get an SSL certificate signed by the FreeIPA server to talk to puppet.  The flow looks like this:

<a href="/assets/images/2013/11/freeipa_foreman.png"><img src="/assets/images/2013/11/freeipa_foreman.png" alt="Here&#039;s a really confusing graphic that may or may not make things clearer" width="590" height="310" class="size-full wp-image-1107" /></a>

<h3>Creating IPA User with Right Permissions</h3>

<b>A previous version of this guide called this user "foreman" - don't do that, it'll interfere with upgrading later, as the RPM packaging expects to use a local user named "foreman."</b>

<ol><li>Create the user:


<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># kinit admin</span>
Password <span class="k">for </span>admin@BITBIN.DE:
<span class="c"># ipa user-add --first="The" --last="Foreman" foreman_reg \</span>
<span class="nt">--password</span>
Password:
Enter Password again to verify:
<span class="nt">--------------------</span>
Added user <span class="s2">"foreman_reg"</span>
<span class="nt">--------------------</span></code></pre></figure>
</li>
<li>Grant host enrollment privileges:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># ipa role-add-member --users=foreman_reg "Host Enrollment"</span></code></pre></figure>

</li>
<li>We need to modify the Host Enrollment role to actually allow the Foreman user to add brand new hosts and delete them too -- so Foreman can completely manage the machine lifecycle.

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># ipa privilege-add-permission 'Host Enrollment' \</span>
<span class="nt">--permissions</span><span class="o">=</span><span class="s1">'Add Hosts'</span>
<span class="c"># ipa privilege-add-permission 'Host Enrollment' \</span>
<span class="nt">--permissions</span><span class="o">=</span><span class="s1">'Remove Hosts'</span></code></pre></figure>


</li>
<li>Change foreman password after first time:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="o">[</span>root@gatebuilder ~]# kinit foreman_reg
Password <span class="k">for </span>foreman_reg@BITBIN.DE:
Password expired.  You must change it now.
Enter new password:
Enter it again:</code></pre></figure>

&lt;/ol&gt;

<h3>Configuring the Create/Destroy Hook</h3>

Grab the scripts from the <a href="https://gist.github.com/stbenjam/7420158">Github Gist</a>.

<ol>
<li>On Foreman, install the hooks gem:


<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># yum -y install ruby193-rubygem-foreman_hooks</span></code></pre></figure>


</li>
<li>And make the directory structure we need:


<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># mkdir -p /usr/share/foreman/config/hooks\</span>
/host/managed/<span class="o">{</span>create,destroy,after_commit<span class="o">}</span></code></pre></figure>


</li>
<li>Put foreman-ipa into /etc/sysconfig/ with the right permissions

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># chown foreman /etc/sysconfig/foreman-ipa</span>
<span class="c"># chmod 600 /etc/sysconfig/foreman-ipa</span></code></pre></figure>

</li>
<li>Configure /etc/sysconfig/foreman-ipa

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># Are we using IPA as the CA?</span>
<span class="nv">CREATE_SERVICE_PRINCIPAL</span><span class="o">=</span><span class="nb">true</span>

<span class="c"># Allow Foreman to delete hosts from IPA</span>
<span class="nv">PREVENT_DELETING_HOSTS</span><span class="o">=</span><span class="nb">false</span>

<span class="c"># Hostname of an IPA server</span>
<span class="nv">IPA_SERVER</span><span class="o">=</span><span class="s2">"astriaporta.bitbin.de"</span>

<span class="c"># User with appropriate permissions</span>
<span class="nv">IPA_USER</span><span class="o">=</span><span class="s2">"registration"</span>
<span class="nv">IPA_PASS</span><span class="o">=</span><span class="s2">"password"</span>

<span class="c"># Foreman API User/Password</span>
<span class="nv">FOREMAN_USER</span><span class="o">=</span><span class="s2">"apiuser"</span>
<span class="nv">FOREMAN_PASS</span><span class="o">=</span><span class="s2">"apipass"</span></code></pre></figure>


<li>Put 10_integrate_freeipa.sh into /usr/share/foreman/config/hooks/host/managed/create and create a symlink to destroy and after_commit:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># ln -s /usr/share/foreman/config/hooks\</span>
/host/managed/create/10_integrate_freeipa.sh ../destroy
<span class="c"># ln -s /usr/share/foreman/config/hooks\</span>
/host/managed/create/10_integrate_freeipa.sh ../after_commit</code></pre></figure>

</li>

<li>Restart foreman to get it to notice the new hooks:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># service foreman restart</span>
<span class="c"># service httpd restart</span></code></pre></figure>

</li>

<li>Take a look at the logs to make sure the hooks were registered, look in /var/log/foreman/production.log:

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">Finished registering 1 hooks <span class="k">for </span>Host::Managed#destroy
Finished registering 1 hooks <span class="k">for </span>Host::Managed#after_commit
Finished registering 1 hooks <span class="k">for </span>Host::Managed#create</code></pre></figure>

</li>

<li>The last step in this is integrating into your provisioning template.  You'll need to get ipa-client installed in your packages list, and remove the other puppet registration thingy from the Foreman. I have a snippet that looks like this:


<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c"># Register to IPA, two times</span>
<span class="c"># in case of https://fedorahosted.org/freeipa/ticket/3377</span>
ipa-client-install <span class="nt">--mkhomedir</span> <span class="nt">-w</span> &lt;%<span class="o">=</span> @host.params[<span class="s1">'ipa_onetime'</span><span class="o">]</span> %&gt; <span class="nt">-f</span> <span class="nt">-U</span>
ipa-client-install <span class="nt">--mkhomedir</span> <span class="nt">-w</span> &lt;%<span class="o">=</span> @host.params[<span class="s1">'ipa_onetime'</span><span class="o">]</span> %&gt; <span class="nt">-f</span> <span class="nt">-U</span>

<span class="c"># Make Puppet Certificate Directories</span>
<span class="nb">mkdir</span> <span class="nt">-p</span> /var/lib/puppet/ssl/<span class="o">{</span>private_keys,certs<span class="o">}</span>

<span class="c"># Generate IPA Certificate</span>
ipa-getcert request <span class="nt">-K</span> puppet/&lt;%<span class="o">=</span> @host.name %&gt;  <span class="nt">-D</span> &lt;%<span class="o">=</span> @host.name %&gt; <span class="se">\</span>
<span class="nt">-k</span> /var/lib/puppet/ssl/private_keys/&lt;%<span class="o">=</span> @host.name %&gt;.pem <span class="se">\</span>
<span class="nt">-f</span> /var/lib/puppet/ssl/certs/&lt;%<span class="o">=</span> @host.name %&gt;.pem

<span class="c"># Workaround for "stack too deep" problem</span>
<span class="c"># http://projects.puppetlabs.com/issues/21869</span>
<span class="nb">cp</span> /etc/ipa/ca.crt /var/lib/puppet/ssl/certs/ca.pem

<span class="nb">cat</span> <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh"> &gt; /etc/puppet/puppet.conf
[main]
    # The Puppet log directory.
    # The default value is '</span><span class="nv">$vardir</span><span class="sh">/log'.
    logdir = /var/log/puppet

    # Where Puppet PID files are kept.
    # The default value is '</span><span class="nv">$vardir</span><span class="sh">/run'.
    rundir = /var/run/puppet
    ssldir = /var/lib/puppet/ssl
    server = &lt;%= @host.puppetmaster %&gt;

[agent]
    # The file in which puppetd stores a list of the classes
    # associated with the retrieved configuratiion.  Can be loaded in
    # the separate ``puppet`` executable using the ``--loadclasses``
    # option.
    # The default value is '</span><span class="nv">$confdir</span><span class="sh">/classes.txt'.
    classfile = </span><span class="nv">$vardir</span><span class="sh">/classes.txt

    # Where puppetd caches the local configuration.  An
    # extension indicating the cache format is added automatically.
    # The default value is '</span><span class="nv">$confdir</span><span class="sh">/localconfig'.
    localconfig = </span><span class="nv">$vardir</span><span class="sh">/localconfig

    certificate_revocation = false
    certname = &lt;%= @host.name %&gt;
</span><span class="no">EOF

</span>puppet agent <span class="nt">--test</span>
chkconfig puppet on</code></pre></figure>

<li>When the machine boots it will use one-time password authentication with FreeIPA and grab an SSL certificate for use with Puppet.  And you get the bonus of when you delete the machine in Foreman, it gets deleted in IPA too.</li>
&lt;/ol&gt;



</li></li></ol></li></ol></li></ol></p></li></ol></p>]]></content><author><name></name></author><category term="foreman" /><category term="technical" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">10-Day Vipassana Course</title><link href="https://stbenjam.github.io/buddhism/2013/08/02/10-day-vipassana-course.html" rel="alternate" type="text/html" title="10-Day Vipassana Course" /><published>2013-08-02T06:05:00+00:00</published><updated>2013-08-02T06:05:00+00:00</updated><id>https://stbenjam.github.io/buddhism/2013/08/02/10-day-vipassana-course</id><content type="html" xml:base="https://stbenjam.github.io/buddhism/2013/08/02/10-day-vipassana-course.html"><![CDATA[<div align="center">
  <a href="/assets/images/2013/08/dhamma-300x300.png"><img class=" wp-image-640 alignleft" alt="dhamma" src="/assets/images/2013/08/dhamma-300x300.png" width="210" height="210" /></a>
</div>

<p><br /></p>

<p>I’ve just returned from five weeks in Southeast Asia, and I have to say it was one of the best experiences of my life.  My time in Asia began with a 10-day Buddhist retreat in the middle of the jungle learning Vipassana.</p>

<p>These courses are free of charge; no money is accepted from any new student. Likewise, no teacher or volunteer receives any payment for their services.  Previous students have paid for you to be there.  It’s intentionally designed this way, and is this way for a similar reason that Buddhist monks beg: it’s incredibly humbling to realize you eat, sleep, and drink only due to the compassion of others.</p>

<p>The web site is <a href="http://www.dhamma.org/">dhamma.org</a>, and you can find a list of centers in many countries (including Europe and the U.S.).  After applying to a 10-day course, you’ll hear back in a few days and get a confirmation if there’s space.</p>

<p>I took the course in Thailand, at the Dhamma Kancana center.  It’s located in the beautiful Thai jungle, about 6 hours by bus from Bangkok.  You can see photos of the center <a href="https://secure.flickr.com/photos/khuntu/3236576892/in/photostream/">here</a>.  It is known as one of the nicest centers in Thailand, but there are several closer to Bangkok if you’d prefer not to atravel far.</p>

<p><strong>What is Vipassana?</strong></p>

<p>From the <a href="http://www.dhamma.org/">website</a>:</p>
<blockquote>"Vipassana, which means to see things as they really are, is one of India's most ancient techniques of meditation. It was taught in India more than 2500 years ago as a universal remedy for universal ills, i.e., an Art of Living. "</blockquote>
<p>These courses are taught by a man named S.N. Goenka, who learned the tradition from his mentor,  Sayagyi U Ba Khin.  There’s other traditions of the Vipassana meditation technique, and details can vary between different Buddhist sects, but largely, the fundamentals are the same.  Goenkaji’s teaching is based in Theravada Buddhism, specifically the Satipatthana Sutta. However, for these courses it has largely had the religious aspects stripped from the teaching.  There’s no mention of Theravada Buddhism in the course, and very little mention of Buddha at all.  There are no statues on the course’s properties, and there’s no focus on one sect over another.  You can be a member of any religion or none.</p>

<p>Modern day Buddhist sects as practiced in Asian countries certainly bolt on a lot of mysticism and rituals that appeal to that culture.  Accept these rituals and rites if they are beneficial to you, or you may disregard them.  It’s entirely up to you.  They are not taught during the course, the focus is on 3 meditation techniques, with the primary one being Vipassana.</p>

<p><strong>Arrival</strong></p>

<p><a href="/assets/images/2013/08/P1000911-300x225.jpg"><img class="size-medium wp-image-607 alignright" alt="P1000911" src="/assets/images/2013/08/P1000911-300x225.jpg" width="300" height="225" /></a></p>

<p>Arrival day is day “0,” which starts sometime in the afternoon.  You’re assigned to a room, eat dinner, and attend the introduction to the course.  The rooms are basic, but adequate.  Some centers have shared accommodations like a barracks, although most have small private rooms.  I was given a room in a 2-room cabin.  It was basic, clean and relatively comfortable.</p>

<p>There weren’t many westerners.  I had expected it to be mostly tourists, but the course was total about 60 people, 85% of the course were Thai, and only 15% foreigners.  A handful of the participants were Buddhist monks.</p>

<p><strong>Noble Silence</strong></p>

<p>Before going to your room however, you’re asked to turn in all of your valuables and distractions including mobile phones, books, laptops, etc.  At Dhamma Kancana, you’re given a private locker and you retain the key so there’s no worry about security.  The reason for this is <strong>Noble Silence</strong>.  During the course you may have no contact with the outside world, nor communicate in any way with your fellow meditators.  Complete silence of speech, body, and mind.</p>

<p>Your bags are not searched to determine if you turned everything in, this is really only for your benefit so you can focus on what you came to do. If you’re communicating, or otherwise stimulating your mind, you will lose your ability to concentrate. After a conversation, and you go into the meditation hall, your mind will still be buzzing with thoughts. It’s very difficult to concentrate and learn if you’re busy thinking about other things.</p>

<p>For me, Noble Silence wasn’t particularly difficult as I’m somewhat of a loner anyway, but the lack of being connected to the world, while jarring for the first couple days,<strong> </strong>I believe was the single most important factor for me being successful during these 10 days.</p>

<p><strong>Precepts</strong></p>

<p>As part of the course, you’re required to accept 5 precepts for the entire duration of your stay:</p>
<ol>
    <li>to abstain from killing any living thing</li>
    <li>to abstain from taking that which is not given freely</li>
    <li>to abstain from all sexual activity</li>
    <li>to abstain from telling lies</li>
    <li>to abstain from all intoxicants</li>
</ol>

<p>The first precept, in addition to meaning you shouldn’t be killing the various bugs you might encounter in the jungle, also translates into a vegan diet; there are no animal products served during the course.  Actually, Dhamma Kancana where I took the course is quite renowned for it’s food.  It is some of the best vegan food I’ve had in my entire life, and I’ve definitely taken some ideas home with me.  I was already vegetarian so I didn’t need much convincing.</p>

<p>As part of Vipassana practice, it’s recommended to continue these precepts after after leaving the course, however it’s not required for the practice, and some may  be modified.  There’s no magic in following these, and there’s no Flying Spaghetti Monster in the sky keeping track.</p>

<p>Goenkaji suggests that being vegetarian is good practice for developing mettā (compassion), however,  Theravada Buddhists, as is practiced in Thailand for example, do generally eat quite a lot of meat.  Other sects of Buddhism are quite strict about it. However, every Buddhist will readily admit that being vegetarian is the better option.  As I’m fortunate enough to live in a wealthy country with many resources, I have a choice in what to eat, and I can’t see taste preference as being a justification to cause the suffering of another living thing.</p>

<p>Post-course, precept #3 is normally taken by lay Buddhists as avoiding “misconduct”, not celibacy. This is also not the Judeo-Christian view of “misconduct”.  Sexual misconduct in the context of Buddhism is any sexual practice that leads to suffering.  Consensual sex between adults of same or opposite genders is allowed.</p>

<p>For old students in the course, there are some additional precepts such as no “high and luxurious beds” and no eating after noon.</p>

<p><strong>Schedule</strong></p>

<p>The schedule is intense, beginning at 4 am and ending at 9 pm every day.  All said and done, you’re meditating for around 10 hours per day.  There’s a set schedule, with about half of the meditation sessions being allowed to be in your room if you wish.  The room is more comfortable as you can sit on the bed with your legs hanging off, instead of having to hold an uncomfortable position in the hall.  There is free time during the day to walk mindfully around the facility, do laundry, clean your room, etc.</p>

<p>Breakfast and lunch are substantial meals, but dinner is only afternoon tea: tea with fruit.   They also had bread and jelly as well during dinner, and occasionally peanut butter.  The days with peanut butter were nice as I could make a PB&amp;J.  The amount food is more than sufficient, you’re not doing a lot of physical activity and should eat less than you think.</p>

<p>The day ends in the late evening with a 1-2 hour video lecture by S.N. Goenka, followed by a 30-45 minute practice session of any new techniques, and an optional time period to ask questions to the teacher in private.   Communication with the staff is allowed, it’s not breaking Noble Silence, but it should be infrequent.</p>

<p>The video lectures are some of the most interesting and engaging things I’ve ever listened to. Goenkaji is a prolific and interesting speaker.  If you’re taking the course and speak English well, opt to view the videos in Goenkaji’s excellent English.  I suspect his charisma is lost in the translations.</p>

<p>On day 10, you are free from your obligation of Noble Silence by mid-morning, and are encouraged to talk again.  It was actually quite odd, I had spoken a couple of times to the teacher during the week, but when I went to say something at normal volume, my throat cracked and I couldn’t talk!</p>

<p><strong>Techniques</strong></p>

<p>Beginning on the evening of day 0, and continuing on days 1, 2, and 3, you are taught a “mindfulness of breathing” technique known as <strong>anapanasati</strong>.  It is as simple as it sounds: you sit and be aware of your breathing.  You don’t control it, but simply remain aware of the breath, the feeling as it enters and leaves your nose, which nostrils it is in, and the feeling on the upper lip.  These first 3 days are useful to build your mind’s concentration.</p>

<p>If you’ve ever sat for meditation before, you know that it’s quite difficult  to maintain concentration.  The mind wanders every few seconds!  Part of the exercise of the first 3 days of anapanasati is to build your ability to stay equanimous when this happens: you simply acknowledge the thought without feeling upset (building compassion for yourself while developing concentration), and you return to breathing.  You’ll notice as the days continue, the mind begins to wander less and less.</p>

<p>On the evening of the 3rd day, you are introduced to <strong>vipassana</strong>. One of the core teachings of Buddhism is that everything in the universe is impermanent (the concept of <strong>anicca</strong>).  Because everything in the universe is constantly arising and passing away, there’s no sense in being attached to it.  Vipassana teaches you to avoid cravings and aversions for anything that happens in life.  Craving and aversion lead to attachment, which always leads to suffering. Vipassana is a meditation technique that intuitively teaches you this lesson; it changes the habit pattern of the mind by giving you direct experience of <em>anicca.</em></p>

<p>So, what exactly is vipassana?  It has to do with observing bodily sensations.  You’ll spend the next 7 days observing your body by examining piece by piece, and acknowledging but not reacting to the various sensations you experience.  Sometimes they are pleasant, sometimes they are not, but they are always impermanent – they will always pass away.</p>

<p>It’s a simple but effective technique.  You are changing your habit patterns in how you react – you develop equanimity, mindfulness, and compassion for yourself using this technique.  It’s hard to explain, which is why you should take the 10 day course to learn it in detail!</p>

<p>The final meditation technique you learn is <strong>mettā bhavana</strong>which is taught in only a few hours on the last day.  It is essentially what you should do at the end of every vipassana meditation session for a few minutes: it’s compassion meditation.  Basically, you’re contemplating and “sending” (if you believe such things are possible) your compassion to specific people or people in general, and as well as yourself.  It’s a way of wishing good feelings for everyone.</p>

<p><strong>Results</strong></p>

<p>I found the course beneficial.  The technique is extremely helpful in becoming a more balanced person, and becoming more mindful of what’s going on in day-to-day life.  I’ve definitely noticed changes in how I react to things that happened.</p>

<p>One interesting side effect in the days following the course was the incredible expansion of my attention span.  <a href="http://www.theatlantic.com/magazine/archive/2008/07/is-google-making-us-stupid/306868/">Google is making us stupid</a>, and blogs are destroying our attention spans.  In the days that followed, I digested a number of pieces of long form writing, including three whole books – and the books were consumed mindfully, often pausing and spending time to think about what was being said.  Vipassana is definitely a cure for at least this modern ill!</p>

<p>I haven’t maintained the practice perfectly, but seem to be able to meditate almost every other day.  However, I was on vacation and in different places so it was hard to keep up.  I hope to try to do the recommended 1 hour in the morning and evening now that I’m back home.</p>

<p>I won’t lie, the course was challenging.  On day 0, as I was laying in bed without any of my electronic crutches like my iPhone, I was looking at out the prospect of 10 whole days dealing with this.  It was frightening. From the outside 10 days seems like nothing; from the inside it seems like everything. <strong><span style="text-decoration: underline;">Days are big, big things when you’re silent, alone, and disconnected.</span></strong></p>

<p>For the first few days, I was counting meals because they seemed like much shorter time periods to adjust to!   At the end of day 1, I kept saying “Ok, look, you’ve already had 4 meals, and you’ve hardly been here any time at all.  You’ve only got 27 more, and they’ll go by faster than you think.”  I worried about what was going on in the outside world, concerned even I hadn’t told my tax accountant I would be offline in case the Finance Ministry had questions about my tax return.   The thoughts faded as the days went on, 27 meals became 18, 18 became 15, and eventually I stopped counting and became content with the disconnection from the world.  It wasn’t without it’s difficulties, though.  One day in particular was hard enough I contemplated quitting.  Everyone going through this course will face some of their own demons, and will have a moment like I did.  It could come on day 3, or on day 9, but it <strong>will</strong> happen.</p>

<p>The day that we learned the Vipassana technique, I could not get my mind under control.  I was fidgeting non-stop, and it was everything I could do just not to walk out the gate to the center and go home.   I was angry: angry at the teacher for making me sit so uncomfortably, angry at not being able to concentrate, and even angry at myself for feeling angry.  At the end of that 2-hour session, I went back to my room and laid in bed, quite upset at how I reacted, how I hadn’t paid enough attention to the teaching, etc.</p>

<p>I began to  think how far too often I’ve made knee jerk reactions in life to uncomfortable circumstances.  I did anapanasati, and calmed myself down. I returned for the next session and made it through the remaining 7 days without significant problems</p>

<p>It’s challenging, you’ll be pushing yourself to the limit of what you think you can do. However, if you persist, you’re bound to be successful.</p>

<p>Bhavatu Sabba Maṅgalaṃ
<em id="__mceDel">(May All Beings Be Happy)</em></p>]]></content><author><name></name></author><category term="buddhism" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Flying the Enchanted Skies</title><link href="https://stbenjam.github.io/trip_report/aviation/2013/04/07/flying-the-enchanted-skies.html" rel="alternate" type="text/html" title="Flying the Enchanted Skies" /><published>2013-04-07T21:49:00+00:00</published><updated>2013-04-07T21:49:00+00:00</updated><id>https://stbenjam.github.io/trip_report/aviation/2013/04/07/flying-the-enchanted-skies</id><content type="html" xml:base="https://stbenjam.github.io/trip_report/aviation/2013/04/07/flying-the-enchanted-skies.html"><![CDATA[<p><a href="/assets/images/2013/04/new_mexico-300x199.gif"><img class="alignleft size-medium wp-image-332" alt="new_mexico" src="/assets/images/2013/04/new_mexico-300x199.gif" width="300" height="199" /></a></p>

<p>With only one full day left of vacation visiting my folks in Albuquerque, my brother and I were brainstorming things I hadn’t done before in the “Land of Enchantment.” He mentioned the Carlsbad Caverns, but we crossed it off the list because of the long drive…until I remembered I had seen flights to Carlsbad on the departures board at Albuquerque.</p>

<p>After some research, I learned that these flights were offered under the <a href="http://en.wikipedia.org/wiki/Essential_Air_Service">Essential Air Service</a> program which provides federally-subsidized air service to remote cities that would otherwise be isolated.  One of the largest companies in this space, Pacific Wings, has several “brands” like Georgia Skies and New Mexico Airlines that operate these contracted flights.</p>

<p><strong>Booking</strong></p>

<p>The New Mexico Airlines web site, like all of the Pacific Wing airlines, is a rebranded version of the parent company’s site.  The web site itself was really easy to use, and return tickets to to Carlsbad were $187 each.</p>

<p>I booked the first flight out to Carslbad, LW02, departing at 7:45, and returning on LW86 at 16:45.  Plenty of time for a day trip to the caverns.</p>

<p>I paid for the flights with my credit card, and received a confirmation e-mail a few minutes later with a true blue <a href="http://en.wikipedia.org/wiki/Passenger_name_record">PNR</a>.  I wasn’t expecting that they had a real travel system on the backend.  It turns out they really are a fully integrated airline with Sabre and Amadeus, complete with baggage interlining agreements.</p>

<p>I was curious to see if this airline was visible in <a href="http://www.expertflyer.com/">ExpertFlyer</a>.  It was – it showed Y7 on the outbound flight, with the aircraft’s capacity at 9.  It looked possible that we the only people booked on the outbound…</p>

<p>Unfortunately, Carlsbad is a one horse town – or rather, a one taxi town, that does not go to the caverns.  There is, however, an Enterprise car rental in the city who will pick you up and drop you off at the airport.</p>

<p><strong>Check-In</strong></p>

<p>The instructions on the web site were clear that you must be at the gate an hour before departure, and I was a little worried I’d have a hard time locating the check-in counter.  We arrived early, but my worries were unfounded because there’s a big sign we spotted immediately after entering the airport that pointed the direction to the New Mexico Airlines check-in desk.</p>

<p><a href="/assets/images/2013/04/P1000719-300x225.jpg"><img class="size-medium wp-image-339 alignright" alt="P1000719" src="/assets/images/2013/04/P1000719-300x225.jpg" width="300" height="225" /></a></p>

<p>No one was staffing the desk, however there was a phone and a sign instructing passengers to pick it up.  I was routed immediately to the Pacific Wings central call center, and the friendly rep completed our “pre-check-in” and gave us directions to the gate (100 meters away).  She told us the pilots would be at the gate shortly to check us in.  Interestingly, there is no TSA security check for these flights, you can walk directly to the boarding gate.</p>

<p>The gate is next to the NMA office, and a bunch of the staff were buzzing around. I had a friendly chat with one them.  Today was a big day for them, they were breaking-in a new (to them) plane.  The livery had just been done the day before, and they were flying it up to Los Alamos for a dog and pony show.  That brings New Mexico Airlines total fleet to 3 Cessna 208B’s.  I got a chance to see the new plane, N307PW:</p>

<p>I looked up pictures of the Cessna 208B’s before I left, and saw some from Georgia Skies, but none from New Mexico Airlines.  The Georgia Skies Cessna’s didn’t seem to have much beyond a default boring plane scheme, so I was pleasantly surprised to see such a good looking livery on these NMA planes.</p>

<p>At exactly an hour before our scheduled departure, a pilot showed up at the check-in counter to take our weights and get our information.  It was here I began to worry: our pilot looked really young – like he had skipped high school classes to fly this morning.  He was also fidgety and nervous, and could have also used a lesson or two on interacting with customers. Thankfully he wasn’t actually the Captain, just the co-pilot who was still learning…</p>

<p><a href="/assets/images/2013/04/P1000420-300x225.jpg"><img class="size-medium wp-image-369" alt="At the gate" src="/assets/images/2013/04/P1000420-300x225.jpg" width="300" height="225" /></a></p>

<p>During check-in, he confirmed we were the only passengers, and then angrily ranted about how the EAS program is a waste of his tax dollars, and he’s often flying these routes with empty planes because of their contract with the Federal government.  I thought it was strange, considering that’s where his pay check comes from.  Also, if you lived in Carlsbad about four hours from the nearest big airport, you’d probably disagree about the worth of the EAS program.</p>

<p><strong>Boarding</strong></p>

<p>About 30 minutes before our departure time, the Captain showed up and it was a night-and-day difference from our co-pilot.  He was older, and had that experienced aviator vibe that can make the most nervous passenger feel at ease.  At 15 minutes before departure, the co-pilot made the announcement to board and we exited the terminal through the glass doors directly onto the tarmac.</p>

<p>As we were boarding the plane, the Captain asked us to sit in the last two seats, I imagine to keep the weight/balance in check.</p>

<p><strong>Cabin</strong></p>

<p>The seats were more comfortable than I imagined, with plenty of leg room, although the lack of a head rest made sleeping precarious.  The seat belt was also over-the-shoulder, and shorter than you would expect.  A taller person would be pretty uncomfortable lashed to the seat.</p>

<p>The plane is equipped with a single set of indicators for seat belts and no smoking.  I do wonder, though, when it would really ever be safe on such a small plane to take off your seatbelt.</p>

<p><a href="/assets/images/2013/04/P1000438-300x211.jpg"><img class="aligncenter size-medium wp-image-385" alt="P1000438" src="/assets/images/2013/04/P1000438-300x211.jpg" width="300" height="211" /></a></p>

<p>Each seat also had a reading light and air vent:</p>

<p><a href="/assets/images/2013/04/P1000437-300x225.jpg"><img class="aligncenter size-medium wp-image-386" alt="P1000437" src="/assets/images/2013/04/P1000437-300x225.jpg" width="300" height="225" /></a></p>

<p>And an oxygen mask in the seat pocket, that would be connected directly to the air vent:</p>

<p><a href="/assets/images/2013/04/P1000454-300x225.jpg"><img class="aligncenter size-medium wp-image-387" alt="P1000454" src="/assets/images/2013/04/P1000454-300x225.jpg" width="300" height="225" /></a></p>

<p>Safety Information Cards:</p>

<p><a href="/assets/images/2013/04/P1000428-225x300.jpg"><img class="aligncenter size-medium wp-image-389" alt="P1000428" src="/assets/images/2013/04/P1000428-225x300.jpg" width="225" height="300" /></a></p>

<p>Each seat was also equipped with a copy of open letters between Pacific Wings and the City of Carlsbad arguing about the EAS contracts. Small town politics at work.</p>

<p><a href="/assets/images/2013/04/P1000433-300x225.jpg"><img class="aligncenter size-medium wp-image-395" alt="P1000433" src="/assets/images/2013/04/P1000433-300x225.jpg" width="300" height="225" /></a></p>

<p><strong>Flight</strong></p>

<p>After we were on board, the pilots completed their take-off checklist, and we began taxiing to the runway.  During the taxi, the co-pilot gave a rather dispassionate and fast security briefing that was a bit hard to understand.  We were in the air quickly after that, and take off was smooth.</p>

<p>This was my first time on a single-engine prop plane, and there was not a single bit of turbulence on the way down to Carlsbad.</p>

<p>Directly around Albuquerque, I was treated to some scenic views through the Cessna’s big, big windows:</p>

<p><a href="/assets/images/2013/04/P1000458-300x225.jpg"><img class="aligncenter size-medium wp-image-398" alt="P1000458" src="/assets/images/2013/04/P1000458-300x225.jpg" width="300" height="225" /></a></p>

<p>But once we left the Albuquerque, the scenery was not quite as exciting, desert as far as the eye can see:</p>

<p><a href="/assets/images/2013/04/P1000461-300x225.jpg"><img class="aligncenter size-medium wp-image-399" alt="P1000461" src="/assets/images/2013/04/P1000461-300x225.jpg" width="300" height="225" /></a></p>

<p>We were in the Carlsbad area about an hour after take off, and things started to look a bit greener:</p>

<p><a href="/assets/images/2013/04/Train-yard-in-Carlsbad-300x225.jpg"><img class="aligncenter size-medium wp-image-402" alt="Train yard in Carlsbad" src="/assets/images/2013/04/Train-yard-in-Carlsbad-300x225.jpg" width="300" height="225" /></a></p>

<p><a href="/assets/images/2013/04/P1000463-300x225.jpg"><img class="aligncenter size-medium wp-image-403" alt="P1000463" src="/assets/images/2013/04/P1000463-300x225.jpg" width="300" height="225" /></a></p>

<p>Landing was as smooth as the take-off.</p>

<p>When we arrived at CNM, the Captain told us to be back by 16:15 for our return flight.  The walk to the terminal building was about 50 meters, and at the door, the Enterprise representative was waiting.  Luckily, we didn’t even need to go into the city: Enterprise had brought the car to us at the airport, and we completed the paperwork in the terminal.  I wish the rental car would always pick me up at the door to the plane! It was very nice of them, that saved us about an hour of time!</p>

<p><strong>Carlsbad Caverns</strong></p>

<p>The Caverns are about a 30 minute drive from the airport:</p>

<p><a href="/assets/images/2013/04/P1000672-300x225.jpg"><img class="aligncenter size-medium wp-image-413" alt="P1000672" src="/assets/images/2013/04/P1000672-300x225.jpg" width="300" height="225" /></a></p>

<p>We got to the caverns about 9:50a.m., too late to join the 10 a.m. tour, so we did the self-guided tour with audio guides.  The Caverns are incredible!</p>

<p><a href="/assets/images/2013/04/Rock-of-Ages-225x300.jpg"><img class="aligncenter size-medium wp-image-416" alt="Rock of Ages" src="/assets/images/2013/04/Rock-of-Ages-225x300.jpg" width="225" height="300" /></a></p>

<p>All in all, it took us about 3 hours to make it through the caverns.  After eating lunch at the restaurant, we still had about 2 hours to kill before our flight.  After some Googling, I found that the<a href="http://www.emnrd.state.nm.us/spd/livingdesertstatepark.html"> Living Desert and Zoo State Park</a> was near by, so we headed over to take a walk around:</p>

<p><a href="/assets/images/2013/04/Road-Runner-300x225.jpg"><img class="aligncenter" alt="Road Runner" src="/assets/images/2013/04/Road-Runner-300x225.jpg" width="300" height="225" /></a></p>

<p><a href="/assets/images/2013/04/P1000689-300x225.jpg"><img class="aligncenter size-medium wp-image-423" alt="P1000689" src="/assets/images/2013/04/P1000689-300x225.jpg" width="300" height="225" /></a></p>

<p>Everything in the park is native to the Chihuahua desert, except for the green house at the end which contains a variety of Cacti from around the world.  The most impressive of which was around 15 feet (4.5 meters) tall!</p>

<p><a href="/assets/images/2013/04/15-foot-Cactus-4.5-meters1-225x300.jpg"><img class="aligncenter size-medium wp-image-425" alt="15 foot Cactus (4.5 meters)" src="/assets/images/2013/04/15-foot-Cactus-4.5-meters1-225x300.jpg" width="225" height="300" /></a></p>

<p><strong>Return Flight</strong></p>

<p>We left the gardens around 15:30 and were back at the airport by 16:00.</p>

<p><a href="/assets/images/2013/04/P1000475-225x300.jpg"><img class="aligncenter size-medium wp-image-427" alt="P1000475" src="/assets/images/2013/04/P1000475-225x300.jpg" width="225" height="300" /></a></p>

<p>The check-in counter is the same process as Albuquerque:</p>

<p><a href="/assets/images/2013/04/P10004711-300x225.jpg">
</a> <a href="/assets/images/2013/04/P1000470-300x225.jpg"><img class="aligncenter size-medium wp-image-429" alt="P1000470" src="/assets/images/2013/04/P1000470-300x225.jpg" width="300" height="225" /></a></p>

<p>We waited in the small seating area until the pilots came again to check everyone in:</p>

<p><a href="/assets/images/2013/04/P10004711-300x225.jpg"><img class="aligncenter size-medium wp-image-430" alt="P1000471" src="/assets/images/2013/04/P10004711-300x225.jpg" width="300" height="225" /></a></p>

<p>By 16:40, we were again on the aircraft, although this time it was relatively full with 7 passengers.  The pilots told us in advance that it would be much bumpier than on the way down, due to high winds.  It was indeed pretty turbulent, although I’ve had much worse on bigger jets.  The Cessna took it like a champ, and the pilots were doing a good job of trying to mitigate it as much as possible.  We spent most of the flight at a pretty low altitude to avoid the bad air.</p>

<p>The flight back was about 20 minutes longer due to the winds, but we landed in Albuquerque right on time around 18:05.  We were home in time for dinner.  The total trip time was around 10 hours.  Driving alone would have taken that long round-trip.</p>

<p>I was really happy with my New Mexico Airlines experience, and will definitely look for other opportunities to fly on these EAS routes.  If you’re lucky, you can get a private plane experience for a fraction of the cost.</p>]]></content><author><name></name></author><category term="trip_report" /><category term="aviation" /><summary type="html"><![CDATA[]]></summary></entry></feed>