SSL Only web app with Clojure, Noir and Ring

I recently needed to make sure that my Clojure web application was listening for SSL connections only. This is the best way to make sure that client credentials are not accidentally sent over an un-encrypted connection.

First, I needed to convert my OpenSSL generated self-signed certificate to a Java Key Store. I found Dr. Herong Yang's Tutorial on the subject to be the best documentation on that step.

I have shorted it down to the following shell script, which takes two arguments; the key and the cert, both in PEM file format.

#!/bin/sh
set -e 

KEYFILE=$1
CERTFILE=$2

# first we need to merge the keys into a pkcs12 keystore
openssl pkcs12 -export -inkey $KEYFILE \
               -in $CERTFILE -out key_crt.p12 \
               -name key_crt \
               -password pass:thisisahardcodedpassword

keytool -importkeystore -srckeystore key_crt.p12  \
         -srcstoretype pkcs12 -srcstorepass supersecret -srcalias key_crt  \
         -destkeystore key_crt.jks -deststoretype jks  \
         -deststorepass thisisahardcodedpassword

I can then call that script on the key and cert my sysdamin utility generated for me (we're running this on an appliance). It creates a Java Key Store in the current directory, called key_crt.jks.

I'm using Noir which itself uses Ring which sits on top of Jetty. The Noir layer requires a port argument, which it passes the the ring constructor. If you then pass a :jetty-options map with :ssl? true and an :ssl-port value, it will open up both ports.

So what I did was write a function which will remove all Non-SSL connectors from the org.mortbary.jetty.Server object, and pass that in as my :configurator argument in the :jetty-options map:

(defn remove-non-ssl-connectors [server]
  (doseq [c (.getConnectors server)]
    (when-not (or (nil? c) (instance? org.mortbay.jetty.security.SslSocketConnector c))
      (.removeConnector server c)
  ))
  server)

Finally, my call to noir.server/start looks like this:

(noir.server/start 8443 {:mode :dev
                         :jetty-options {:configurator remove-non-ssl-connectors
                                         :ssl? true
                                         :ssl-port 8443
                                         :keystore "/path/to/my/key_cert.jks"
                                         :key-password "thisisahardcodedpassword"}
                         :ns 'my.app})

The result is that my Noir app listens on port 8443 for SSL connections, and only that port, and only does SSL. Woot.


Tension Between Text and Taxonomy

I just added the RSS feed support, and in the process of doing another round of work on my blog app, I found that I was wavering back and forth on some decisions about how to write the code. I was trying to find a sweet spot between the readability of the code as text, and the modularity or structure of the code as functions, namespaces, and such.

Taxonomy

We often think of the semantic, and runtime organization of the code as the primary arena for expressing quality in the code. We ask questions like:

  • Are my classes properly identified?
  • Are my interfaces composable?
  • Do my interfaces leak implementation assumptions?
  • Do my implementations assume things the interface does not guarantee or express?

I'm gonna call this the Taxonomy -- breaking the system into parts, naming them, defining their operation as distinct from the rest of the complex system they are embedded in, so that they can be removed from it and plopped into another one.

In the effort to get all of our components un-entangled, we find ourselves isolating decisions and assumptions into their own blocks. We get a proliferation of small interfaces to isolate components that are unlikely to be used distinctly from one another. We define configuration variables that are only used once.

I have seen (and written) code where this tendency is expressed as a nearly impossible to navigate nested set of classes, with each class putting barely a gloss on the ones below it -- sometimes doing nothing more than providing default args for the constructor! It can be like reading something as operationally simple as The Three Little Pigs in the formalized language of a legal briefings.

You want to track just one simple thread of information propagation, or execution, and end up touching 10 files. Your emacs has almost as many buffers open as you have lines in the stack trace!

Ok, so I'm describing the absurd ends of this tendency to complexify in the name of abstracting, isolating, and decomposing semantics components of the code. That's so you recognize it in your gut.

Text

We have style guides, and conventions just like journalists and other writers. There are accepted, but still contentious, ways of formatting the code to make it easier to scan and move through. Some go so far as to embed the program in a descriptive text; literate programming.

The tools for Literate Programming have to provide a way of resolving the tension between the order of presentation and narrative targeting a human reader. CWEB for example let's you tell it where the code snippet goes when compiled. This lets you present the reader something and then define it's dependencies afterwards.

This is one vector of tension between Taxonomy and Text, *order of presentation*.

In some systems I have worked in, you come to the project and fall into a directory full of classes or modules. Maybe a README tells you where to start reading, but then it's jumping around attempting to turn this collection of objects into threads of execution and information flow.

This is another vector of tension, lack of narrative.

Unlike a narrative presentation, there is little redundancy, or re-presentation of something within the multiple contexts it is used. The DRY principle can result in the human reader having to maintain a giant state table in their brain to do something computers do almost for free, interpolate values. Hopefully the names of variables and such are well-chosen, but that only helps so much.

And another vector of tension, interpolative overhead.

Because our text is laid out in files that usually map to classes or modules, we have to jump around. Our IDEs or editors can make this easier, but even a single click to find referrers of a symbol doesn't stop the cognitive jolt of jumping to a huge list of references or a new source file.

This vector of tension I call textual disjunction.

Lastly, we get an idea of all the parts of the animal, but it requires much closer reading to get an inkling of how they fit together beyond the level of gross anatomy. Our languages, OO in particular, empahsizes the definition of what exists, the ontology of our problem domain, but very poor tools for describing the dynamics of the composition of those things.

This vector of tension I think of as ontological fixation.

Ok, so these vectors of tension are not earth-shattering conflicts, or roadblocks. We obviously all work through them to various degrees of success. I'm not trying to point out some failing of OO, or other crisis of software development.

So if there is not a global software crisis that is going to cost *ALL THE JOBS*, or something like that, why am I bringing this up?

Textual Specificity

So you built your conglomerative app, layers of frameworks, each with their own properties file, and you have config files for each deploy environment. They tell the pieces how to fall together, which "Factory" object should create what class when asked for something implementing the "Foo" interface.

You re-use code by pulling in frameworks that are targeting a general problem, which target an abstraction of the actual problem you face. Then you either shoehorn your real problem to fit the abstraction, with glue classes and other connective tissue prone to inflammation.

I've done this for years, and while you can get it to work most of the time, it's frustrating to work with, confuses the hell out of people, and prone to both bugs and a kind of textual ossification due to abstraction overload and impedance mismatch.

What alternative is there?

Well, I'm thinking of something, I'll call it textual specificity for now. It means re-using code that way story tellers re-use characters and plot devices and narrative elements.

They don't refer to some set of paragraphs in another book with the canonical specification and description of the "uptight, overly pedantic git" character. They take the archetype, and rewrite it to fit their tone, and mutate it to mesh with the context/storyline they are weaving.

As a culture, programmers frown on that, and unless there is significant re-writing we would deride it as cut and paste coding.

What if textual recombination, and I don't mean macros, was our way of re-using code? Read the code that solves a similar problem, and then write a version of it tuned to your specific problem, to the reality your program has to interact with.

Sure, someone has to read your code and maintain it, but when the cost/benefit ratio for adding yet another gem dependency to my Rails or Java app is so bad, I'll take a chance getting my code right vs. juggling deps across version incompatibilities in a massive ecosystem.

I want to spend my time getting my code to match my problem, not spend it fighting off death by a thousand impedance mismatch papercuts within my cloud of overstuffed frameworks.

If you are not constrained by some OO straightjacket, put more code in fewer files. Don't be the project DRY nazi. Imagine yourself as the reader starting from the top of the file and going down. Describe your problem right next to the solution.

Instead of giving the reader switches and config variables, make the text easy to read and edit as they see fit. They'll probably want a function where you have a scalar anyways, dude.

Ok, this is starting to sound like Programming, Motherfucker rant. Probably should wrap it up.

Inconclusion

There is no crisis, and this is no panacea, and Textual Specificity can swerve off the road and into the ditch of "Not Invented Here" and the fragmentation of community that plagued the Common Lisp world.

I'm suggesting we keep in mind that our programs are texts, and that the beauty of their form comes not from the generality of the abstractions we compose them from, but from the clarity and fit with which they interface with their ecological niche.

Hows that for miscegenating metaphors?

I must now pass beyond the veil of sleep, see you in Kadath.


My Introduction to Worker Cooperatives

Yesterday I met with two neighbors, Tom and Emily, who specialize in developing cooperatives, It was a continuation of a conversation we started in a bar, of course. They listened patiently as I tried to outline my rather abstract notion of what kind of coop I wanted to build or work for.

By the end of brunch they had given me several places to start my investigation, some guidance on the legal structures available, and pointers to existing worker coops that worked with technology or had similar ideas. They also helped me plan the next steps, namely developing my ideas some more, and in more concrete terms, and finding other people.

I spent the day following the breadcrumbs they provided, and here are the results:

Definitions of Worker Cooperatives

Tom suggested I contact the Democracy At Work Network, and gave me an idea of what I should have done before I do so.

They define member worker cooperatives by the Oslo Declaration which was written by the CICOPA. The Oslo Declaration refers to the Statement on the Co-operative Identity as defined by the International Cooperative Alliance.

Finding other Worker Coops

Democracy At Work Network

US Federation of Worker Coops

A Model for Thinking about Coop Culture

Within the DAWN reading room, I came across a paper, Does Cooperation Equal Utopia. It is a survey of three worker coops, and includes a quick reading introduction to the authors analytic model, which is based on Edgar Shein's work on organization culture.

In Edgar Schein's model of organizations, the Basic Assumptions are pre-conscious, invisible, or taken for granted, but are also the foundation for the value system and cultural justifications of the work. Presented as examples of such assumptions are:

  • relationships to the environment
  • nature of reality and truth
  • nature of human activity
  • nature of human nature
  • nature of human relationships

While these are the foundation of the organizational culture, they are also enacted and created, or re-enforced over time. They are not static, tho they may be difficult to change.

This makes me ask a few questions:

  • The pre-conscious or invisible nature of them is not permanent. We can investigate them ourselves, learn about the history of them, how we inherited them or formed them, how they change over time.

  • What do we know about how these assumption percolate up into more visible value systems?

  • What do we know about how actions and material conditions of the culture press back down on the basic assumptions.

I suppose these are rather basic questions within the field of organizational culture, but I'm not familiar with the literature. The model also reminds me of the kind of analysis Istvan Meszaros has done in Social Structure and Forms of Consciousness.


Voice

I sat down to take my next step, to write the next post, and soon had 100 lines of text in someone else's voice.

It was someone I admire and whose writings have been a part of my thought for over a decade. I was then filled with a sense of dread. How could I live up to such a voice? Was that really the voice I needed?

The dread turned into frustration, then a sense of being overwhelmed by the scope of what I wanted to write about. In my mind, the phrase:

I want to create a historically maintainable, hegemonic alternative to the social-metabolic order of capitalism.

sounded sensible, precise, and inspiring. I doubt it rings like that in other ears though. I thought I would explain all the terms, unpack it. Soon I was planning out a grand essay, or a book. I would have to be rigorous and extensive in my presentation of my thought. I would have to defend it against critics who had no interest in improving it, only destroying or discrediting it.

So I took a break and had a beer.

The Conversational Voice

I get into conversations at bars frequently. I am careful. I start slowly, let questions indicate further interest, and I limit my scope and detail to appropriate levels.

This could be a useful voice, but I have some issues with it, and as a voice for writing it suffers from lag in feedback. Its vocabulary adjusted, its pace tuned, as I learn more about the audience. That voice is not a very precise guide here, where an audience is only an abstraction for now.

There is another problem, though.

I am practicing my writing in order to develop the ideas I have, and to share them with others so they can grow. A conversational voice that is torn between where the audience is at, and where my head and hopes of the future are at.

The Academic Voice

I enjoy reading critical theory and philosophy, but it has taken me years to absorb the jargon and context. In a few cases, it could be avoided, but it serves a purpose -- letting a community talk about a very large and complex topic for several generations. Mix in all of the nuances of human expression, desires to perform a given aesthetic, or differentiate oneself from subgroups in the topic, and you have a rich, florid, extravagant field of language that makes a rococo cathedral look like your high school's trophy case.

Since these are conversations spanning lifetimes, we find ourselves going back to the words of the dead. Many times you only read a summary of the ideas, or one take on what was said. Eventually you will find that the retellings lose alot of the original story, intent, and depth.

The obvious downside here is that you are asking your reader to be responsible for alot of work. The not so obvious penalty is that you are tying your ideas to a big network of thought. You will find yourself spending lots of energy differentiating your use of the word from other peoples use, and fighting ancient wars whose generals are long dead.

The Obligatory Synthesis

So what components of these two voices can we use within the framework of a blog?

  • Serial Presentation -- blog pieces are distinct installments, with a presentation in series when archived. This can record some aspects of the development of the conversation, and the mutations of the thoughts over time. Bit by bit a corpus can be built, with later pieces developing previous topics further -- as the reader feels fit to progress. Lastly, the pace and order of presentation can be tuned as feedback trickles in.

  • Short Pieces -- with the largest piece being perhaps a short essay, specific topics must be chosen, or light sketches must be drawn. This can help preserve simplicity, and supports a conversational tone.

  • Hypertextuality -- referring to previous posts, and linking to external references helps build a network of thoughts. It also eases the burden on the reader to learn jargon if links are provided for new terms, or terms with less orthodox definitions. Links to original sources make it easier for the reader to check the words of the dead against the stories we tell about them.

  • Aggregations -- After a corpus has accumulated, new pieces can be built by following threads across topics, or by providing an overview of a multi-faceted topic.

  • Feedback -- Having survived Usenet, I am skeptical of the value of comments. As a curmudgeon, I am loathe to type into web forms. I think email is still the preferred way to get feedback, and it lets me read and respond in my native environment, Emacs.

Where that leaves me

Sitting in the bar, trying to build a path to the future, one conversation at a time.


First Steps

I am building a simple blog app using Clojure and Noir. It runs from a git repo. Pages and posts are files I can edit in Emacs. It runs on Heroku, who graciously provides free hosting for small projects like this.

The entire site, content included, is available at:

https://www.github.com/craigbro/practice

I'm doing this because I want a space to practice my sharing, my writing. Part of that is developing a voice that can carry more than a tweet or an email conversation. I wrote my own blog software because it was the only way for me to not be annoyed by ill-fitting tools.

This is my initial post, these are my first steps.