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

<channel>
	<title>Adam Young's Web Log</title>
	<atom:link href="http://adam.younglogic.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://adam.younglogic.com</link>
	<description>The Notebook of a Programmer Climber Musician Ex-Soldier</description>
	<lastBuildDate>Wed, 16 May 2012 20:01:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Signed Authentication and Authorization</title>
		<link>http://adam.younglogic.com/2012/05/signed-authz-authn/</link>
		<comments>http://adam.younglogic.com/2012/05/signed-authz-authn/#comments</comments>
		<pubDate>Wed, 16 May 2012 14:31:05 +0000</pubDate>
		<dc:creator>Adam Young</dc:creator>
				<category><![CDATA[Openstack]]></category>
		<category><![CDATA[PKI]]></category>

		<guid isPermaLink="false">http://adam.younglogic.com/?p=2135</guid>
		<description><![CDATA[Openstack Keystone currently operates on-line validation for Tokens.  Once a token is issued out,  each of the systems presented with the token has to check the validity of the token with the Keystone server.  This makes Keystone the highest traffic &#8230; <a href="http://adam.younglogic.com/2012/05/signed-authz-authn/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Openstack Keystone currently operates on-line validation for Tokens.  Once a token is issued out,  each of the systems presented with the token has to check the validity of the token with the Keystone server.  This makes Keystone the highest traffic service in an Openstack deployment.  Using Cryptographic Message Syntax (CMS) we can generated a token that can be verified using public key cryptography instead of making a network call.  Here&#8217;s a proof-of-concept example using the command line tools.</p>
<p><span id="more-2135"></span></p>
<p>For authorization, we need a user name.  For authentication, we need a tenancy and a set of roles that the user has in the tenancy.<br />
Authorization cannot be for ever, so we need an expiration date/time.  Here is a simple JSON representation of that data.</p>
<pre class="brush:python">

{"user": "ayoung",
"tenant": "coop-city",
"role": ["hallmonitor, groundskeeper"],
"expiry":"18JUL2012"
}
</pre>
<p>Note that it has the Roles listed in it.  By cryptographically verifying this document,  not only does it remove the need to validate the token with Keystone,  but it removes the need to go back to keystone to fetch the roles.  Thus, authentication and authorization information are linked in one document.</p>
<p>The following assumes you have a signing certificate.  <a href="http://adam.younglogic.com/2012/05/signing-certutil/">See the steps here to generate one if you need it.</a></p>
<p>To Sign auth_token.json run:</p>
<pre class="brush:bash">
cmsutil -S -d alias -N ayoung -i auth_token.json -o auth_token.p7s
</pre>
<p>The signed message is put into auth_token.p7s,  a file extension that alludes to the PKCS 7 standard.</p>
<p>This includes all of the certificates.  Use a tool to view the contents in human readable form:</p>
<pre class="brush:bash">
 /usr/lib64/nss/unsupported-tools/derdump -i auth_token.p7s
</pre>
<p>The output is big.  To simply read the message back, use:</p>
<pre class="brush:bash">
cmsutil  -D -i auth_token.p7s  -d alias/ -h1
</pre>
<p>This gives back the additional file, along with the validated signer:</p>
<pre class="brush:bash">
SMIME: 	level=1.2; type=signedData; nsigners=1;
		signer0.id="Adam Young"; signer0.status=GoodSignature;
	level=1.1; type=data;
{"user": "ayoung",
"tenant": "coop-city",
"role": ["hallmonitor, groundskeeper"],
"expiry":"18JUL2012"
}
</pre>
<p>To simply check if the document is valid,  drop the h1 argument.  If to test it against an NSS database that does not have the CA cert in it, you get:</p>
<pre class="brush:bash">
# cmsutil  -D -i auth_token.p7s  -d altdb

signer 0 status = SigningCertNotTrusted
cmsutil: problem decoding: Peer's Certificate issuer is not recognized.
</pre>
<p>To make this usable as a replacement for the current token scheme,  we could use something like Base64 encoding:</p>
<pre class="brush:bash">
[ayoung@ayoung cmstest]$ base64 auth_token.p7s
MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCAJIAEbXsidXNl
ciI6ICJheW91bmciLCAgCiJ0ZW5hbnQiOiAiY29vcC1jaXR5IiwgIAoicm9sZSI6IFsiaGFsbG1v
bml0b3IsIGdyb3VuZHNrZWVwZXIiXSwKImV4cGlyeSI6IjE4SlVMMjAxMiIKfQoAAAAAAACgggIG
MIICAjCCAWugAwIBAgICCSkwDQYJKoZIhvcNAQEFBQAwFDESMBAGA1UEAxMJTXkgSXNzdWVyMB4X
DTEyMDUxNTIwNDcxNFoXDTEyMDgxNTIwNDcxNFowUzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1B
MREwDwYDVQQHEwhXZXN0Zm9yZDEPMA0GA1UEChMGUmVkSGF0MRMwEQYDVQQDEwpBZGFtIFlvdW5n
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7lNCEwdZMHIClZJ9f84R1tfgEjtZV2H+Nx1OR
eqeK+WYvVXSVJ61g/Vl3ponv8L/qRiqbuyP7Nfr7ogfM2OJuDOiWsyfHJSIS29NVOb5f6+oPw39Q
+fN7NSssTEr6UFz4d1mXl85iJXK+K7x5TGFQowA6po102YCj6tjesGPODQIDAQABoyQwIjAgBgNV
HSUBAf8EFjAUBggrBgEFBQcDBAYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAt105m7XYBugD
y+PXYq7R2XaAdyJGCBl4yq3Xz3qmfYmpP8wVTNy5j2dacuopq+W4DB0CeGo5+sYGAiRSgF8vNx6/
wMt3+EExdJO+IJl9QMRB6ooRzSMJAIH3b3jXOWln9TV6AHLHER8NWoNZq3moSYp4fO8tUVgerDKJ
7TdBP/IxggFaMIIBVgIBATAaMBQxEjAQBgNVBAMTCU15IElzc3VlcgICCSkwCQYFKw4DAhoFAKCB
lzAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMCMGCSqGSIb3DQEJBDEWBBRBECaXMyVVMoW2yonU
kWwriSqs5TApBgkrBgEEAYI3EAQxHDAaMBQxEjAQBgNVBAMTCU15IElzc3VlcgICCSkwKwYLKoZI
hvcNAQkQAgsxHKAaMBQxEjAQBgNVBAMTCU15IElzc3VlcgICCSkwDQYJKoZIhvcNAQEBBQAEgYAV
UCVEsgfo3SK5p5ZF98uWgoIjmyCksS7mULJMT/ZJZJqIyTVY6AmXWCgxzKOHqrzWCansSilYAYQr
aeEgCYjX9GvSxHFmCQQzYM2buzJr5GjoPZJ0osOulUzWX8Nzq5Y51DAcWtU8c+06Ezbu5q5YjBno
2fTEWwYcemr9m/SA7AAAAAAAAA==
</pre>
<p>The break is due to how it is displayed in the browser,  but that is really one long stream of characters.  The value can be sent just like the current tokens, in the -X-Auth-Token header.  Now a remote service can validate the token by reversing the Base64 ENCODING AND using cmsutil or the corresponding APIs.</p>
<pre class="brush:bash">
cat auth_token.p7s.base64  | base64 -d |  cmsutil  -D -i auth_token.p7s -d alias/
</pre>
<p>There are still  a few wrinkles to iron out.  </p>
<ul>
<li>The token is a little longer than it needs to be, due to the certificate being embedded.  For Keystone,  remote systems would be better off fetching the certificate once from the Keystone server,  and just matching the serial number in the CMS token.  </li>
<li>The current scheme of using the token in the URL would probably not work very well with the long Base64 encoding above,  but that system has other known issues, and is likely to be replaced shortly with a scheme that will instead put the token into the body of the document.  However, even that step will be unnecessary with certificate based verification.</li>
<li>Signing documents from Python currently requires calling out to additional processes. <a href="https://bugzilla.redhat.com/show_bug.cgi?id=821971" title="Bug 821971 - Add support for document signing like cmsutil" target="_blank">The Python-NSS maintainer is aware of the issue</a>, and is looking into making a Python-appropriate set of bindings for the CMS calls in Python-NSS.</li>
<li>Since there is no revocation of the tokens,  their lifespan should be kept short.  10-30 minutes is probably appropriate.  The default value will require some consensus</li>
<li>Adding roles for a user will require getting an additional token.  The old token will still be valid,but will not allow the user to do any actions that require the new role.</li>
<li>The code that checks roles does not currently know about the token.  It will require  a small amount of code changes to make sure that the token is available to this code.</li>
<li>While this scheme is backwards compatible with the current auth scheme, the reverse is not true.  Short of checking the length of the token,  there is no way to confirm that a token is a cryptographically signed document as opposed to the alpha-numeric cookie in current usage.  One approach for transition may be to test reading the document, and, upon failure,  fall back to the online protocol.</li>
</ul>
<p>Update:  Revocation will be discussed in an additional article.  </p>
]]></content:encoded>
			<wfw:commentRss>http://adam.younglogic.com/2012/05/signed-authz-authn/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Generating a Signing Cert using certutil</title>
		<link>http://adam.younglogic.com/2012/05/signing-certutil/</link>
		<comments>http://adam.younglogic.com/2012/05/signing-certutil/#comments</comments>
		<pubDate>Wed, 16 May 2012 13:53:45 +0000</pubDate>
		<dc:creator>Adam Young</dc:creator>
				<category><![CDATA[PKI]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://adam.younglogic.com/?p=2151</guid>
		<description><![CDATA[Imagine a locked room with a big window. If I am the only person with a key to room, and I tape a poster up inside the window, everyone can read it, and everyone can state with a pretty high &#8230; <a href="http://adam.younglogic.com/2012/05/signing-certutil/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Imagine a locked room with a big window.  If I am the only person with a key to room, and I tape a poster up inside the window,  everyone can read it,  and everyone can state with a pretty high degree of certainty that I was the person that I put up the poster.  This is analogy to how you can use  PKI to sign a document.</p>
<p><span id="more-2151"></span></p>
<p>In order for the message signature to be verifiable,  we generate a pair of keys, one that is kept private, and one that is made public.  Data encrypted with the private key can then be decrypted with only the corresponding public key.  So, to sign a message, it is encrypted with the private key.  </p>
<p>There are ways to make this more efficient, such as signing a hash of the message,  but the principal is the same.</p>
<p>I am going to use the same set of cryptographic tools that Mozilla provides for securing web traffic.  These tools fall under then name <strong>Network Security Services</strong>  or NSS for short.</p>
<p>The first step is to provide a Certificate Authority (CA) Certificate.  This is a certificate used to sign other certificates.  This is actually supposed to be part of a chain.  In the browser, there are a list of CA certs that are accepted by default.  For our purposes here,  I am going to self sign one.  Figuring out how to set this up for your organization has been left as an exercise to the reader.</p>
<p>We need a place to put the certificate.  For NSS,  this is called an NSS database.  I am going to create one in a directory I call <em>alias</em>, because that is the name of the NSS database used in Apache HTTPD. To generate:</p>
<pre class="brush:bash">
mkdir alias
certutil -N -d ./alias/
</pre>
<p>Now create a self-signed CA certificate. Type the command:</p>
<pre class="brush:bash">
certutil -S -s "CN=My Issuer" -n myissuer -x -t "C,C,C" -1 -2 -5 -m 1234 -d alias/
</pre>
<p>You will be prompted to type.  This is used to generate entropy, or randomness, for the underlying cryptography.</p>
<p>Then you will be prompted to select aspects of the certificate.  A menu of options like this:</p>
<pre class="brush:bash">
		0 - Digital Signature
		1 - Non-repudiation
		2 - Key encipherment
		3 - Data encipherment
		4 - Key agreement
		5 - Cert signing key
		6 - CRL signing key
		Other to finish
</pre>
<p>Type each number in order. 0 1 2 3 4 5 6. The menu will reappear after each.</p>
<p>Yes, it is annoying.  I didn&#8217;t write the tool.</p>
<p><strong>then type any number to finish</strong></p>
<p>So the number 9 works.</p>
<pre class="brush:bash">
 9
Is this a critical extension [y/N]?
y
Is this a CA certificate [y/N]?
y
Enter the path length constraint, enter to skip [<0 for unlimited path]: >
Is this a critical extension [y/N]?
y
</pre>
<p>Not done yet:  Next menu.</p>
<pre class="brush:bash">
		0 - SSL Client
		1 - SSL Server
		2 - S/MIME
		3 - Object Signing
		4 - Reserved for future use
		5 - SSL CA
		6 - S/MIME CA
		7 - Object Signing CA
		Other to finish
</pre>
<p>For this we want 5 6 7  then again pick 9 to exit.</p>
<pre class="brush:bash">
 > 9
Is this a critical extension [y/N]?
y
</pre>
<p>The security conscious folks out there are squirming in their seats reading this,  because a self-signed CA cert is BAD under most circumstances.  However, this is proof-of-concept type stuff.  You always need to get a certificate signed by a CA&#8230;this is just the simple way to do it for development.</p>
<p>Now that we have a CA cert,  we need to generate a Key. With NSS, you can generate the Key and the certificate signing request in one step:</p>
<pre class="bursh:bash">
 certutil -R -s "CN=Adam Young, O=RedHat , L=Westford, ST=MA, C=US" -p "617-555-1212" -o mycert.req -d alias
</pre>
<p>You see the same entropy generation prompt as before.</p>
<p>You can list the keys using:</p>
<pre class="brush:bash">
certutil -K -d ./alias/
</pre>
<p>Which produces output along the lines of:</p>
<pre class="brush:bash">
certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and Certificate Services"
< 0> rsa      99f6d153a007f8fb2d79312d454749eb92e4db99   NSS Certificate DB:myissuer
< 1> rsa      b8472a65af1c2da900fb0eb953d9c278d615a580   NSS Certificate DB:ayoung
</pre>
<p>Note that there is one in there for the CA certificate we produced before.</p>
<p>To sign the key  run the following:</p>
<pre class="brush:bash">
 certutil -C -m 2345 -i mycert.req -o mycert.crt -c myissuer -d ./alias/ -6
</pre>
<p>Here is the menu you are presented:</p>
<pre class="brush:bash">
		0 - Server Auth
		1 - Client Auth
		2 - Code Signing
		3 - Email Protection
		4 - Timestamp
		5 - OCSP Responder
		6 - Step-up
		Other to finish
</pre>
<p>The import options are 1 and 3, as we are going to use the same mechanism as we would use to sign email.  The private and public keys are held in the NSS database.  OK,  we finally have a useful certificate and key pair that we can use to sign a document.  To Sign auth_token.json run:</p>
<pre class="brush:bash">
cmsutil -S -d alias -N ayoung -i signme.txt -o signed.p7s
</pre>
<p>The signed message is put into signed.p7s.  The file extension alludes to the PKCS 7 standard that CMS grew out of.</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.younglogic.com/2012/05/signing-certutil/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The Path to Kerberos over Port 443</title>
		<link>http://adam.younglogic.com/2012/05/path-to-kerberos-443/</link>
		<comments>http://adam.younglogic.com/2012/05/path-to-kerberos-443/#comments</comments>
		<pubDate>Sat, 12 May 2012 01:14:27 +0000</pubDate>
		<dc:creator>Adam Young</dc:creator>
				<category><![CDATA[FreeIPA]]></category>

		<guid isPermaLink="false">http://adam.younglogic.com/?p=2118</guid>
		<description><![CDATA[While Kerberos&#8217; reputation as a Single Sign On solution is quite strong, its adoption outside the corporate VPN has been limited. One reason is that many host providers block port 88 traffic in the firewalls. What would it take to &#8230; <a href="http://adam.younglogic.com/2012/05/path-to-kerberos-443/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>While Kerberos&#8217; reputation as a Single Sign On solution is quite strong, its adoption outside the corporate VPN has been limited. One reason is that many host providers block port 88 traffic in the firewalls. What would it take to make Kerberos a viable solution in a web-only constrained situation?</p>
<p><span id="more-2118"></span></p>
<p>Kerberos communicates over port 88 in order to secure tickets that will be used for authentication and (to a limited degree) authorization on other servers.  This communication is done using the Kerberos wire protocols.  First the user requests a ticket granting ticket (TGT).  Later, the user will use that TGT to get a ticket specific to the service they are trying to talk to.</p>
<p>The connection to get the TGT is a two way street.  There are multiple messages and back and forth as both sides performs steps necessary to prove to the other that they are indeed,  who they claim to be.  This cannot be done over straight HTTP without serious reworking,  but it can be done using a techonology called <a title="Websockets" href="http://en.wikipedia.org/wiki/Websockets" target="_blank">websockets</a>.  With websockets,  the connection between client and server remains open, and HTTP becomes a tunneling protocol for TCP.</p>
<p>Thus, the two things we need to do to get a TGT are:</p>
<ol>
<li> Place the Key Distribution Center (KDC)  behind a <a title="Websockets" href="http://en.wikipedia.org/wiki/Websockets" target="_blank">websockets</a> Proxy.</li>
<li>Create a modified version of the kinit program that can talk websockets,  or build a client side proxy.</li>
</ol>
<p>There are other approaches, of course.  FreeIPA can request a TGT on the server on behalf of the user.  The user could download this TGT, and a Browser plugin could even stick it into the Kerberos Credentials Cache.  But this bypasses the Kerberos ideal of the users password never crossing the wire.</p>
<p>We could write the kinit code into the browser itself, using either a native extension or Javascript,  but it is a complicated enough of a protocol that forking from the C code would be a hefty maintenance effort.</p>
<p>The second step is trickier:  getting the service ticket.  This action is performed for the user automatically when visiting a web site that is protected by, for example, mod_auth_krb.  The web server responds to a request with a 401 and enough information that the browser knows to try Kerberos&#8230;by way of two wrapper libraries called SASL and GSSAPI in turn.  Unfortunately,  this is a pipeline that is pretty much welded shut:  without modifying  either the browser or the Kerberos libraries,  there is no way to automatically request and inject a service ticket on behalf of the user.</p>
<p>It would be possible for the user to do it explicitly, though.  That might be an OK stop-gap measure.  Again, a custom client of some sort could fetch the service ticket and push it into the Kerberos credential cache.</p>
<p>I think the most straight forward path would be to :</p>
<ul>
<li>Extend the Kerberos libraries to be able to talk Web Sockets as a tunnel for the Kerberos wire protocol.</li>
<li>Allow a krb5.conf option that will specify that the KDC is reachable via websockets.  This would be something along the lines of an krb5.conf line</li>
</ul>
<blockquote><p>kdc = wss://kerberos.younglogic.com/kdc</p></blockquote>
<ul>
<li>This value should also be available as a SRV record out of DNS:</li>
</ul>
<blockquote><p>NAME: _kerberos._wss</p>
<p>TYPE: SRV:</p>
<p>VALUE:wss://kerberos.younglogic.com/kdc</p></blockquote>
<p>As a simple proof of concept,  a websocket proxy can run on the client, listening on localhost:88 and talking via Websockets to the KDC.  Then the krb5.conf file can point to the local proxy instead of the KDC Websocket proxy.</p>
<p>Websockets is a simple enough protocol that writing it into the Kerberos code base should not be prohibitive.  If desired,  it could be done as a separate shared object for the general consumption of the system.</p>
<p>It is not necessary to run the TGT fetching code over wss,  the SSL version of web sockets, as the handshake already sets up encryption.  But there is no drawback to running the whole thing over SSL and it will mask any KDC traffice that is not encrypted.</p>
<p>An additional advantage is that now kpasswd can be run on the same port as the rest of the KDC based services, just on a different URL.</p>
<p>Since Websockets is supported by all the major browsers,  making browser plugins to communicate with the KDC is viable.</p>
<p>There might well be other issues of scale:  protecting against DOS attacks and the like, but there is a path forward to a secure WebSSO.</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.younglogic.com/2012/05/path-to-kerberos-443/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>My Openstack Tasks</title>
		<link>http://adam.younglogic.com/2012/05/my-openstack-tasks/</link>
		<comments>http://adam.younglogic.com/2012/05/my-openstack-tasks/#comments</comments>
		<pubDate>Thu, 03 May 2012 02:15:22 +0000</pubDate>
		<dc:creator>Adam Young</dc:creator>
				<category><![CDATA[Openstack]]></category>
		<category><![CDATA[PKI]]></category>

		<guid isPermaLink="false">http://adam.younglogic.com/?p=2119</guid>
		<description><![CDATA[Now that Folsom development has started in earnest,  I figured I&#8217;d follow Russell&#8216;s example and write down a bit of my plan for work in the next couple of months. To date,  my involvement with Openstack has focused primarily on &#8230; <a href="http://adam.younglogic.com/2012/05/my-openstack-tasks/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Now that Folsom development has started in earnest,  I figured I&#8217;d follow <a href="http://russellbryantnet.wordpress.com/2012/04/24/openstack-design-summit-and-an-eye-on-folsom/" target="_blank">Russell</a>&#8216;s example and write down a bit of my plan for work in the next couple of months.</p>
<p><span id="more-2119"></span></p>
<p>To date,  my involvement with Openstack has focused primarily on Keystone.  Using that as a starting point,  I want to continue it in two directions: deeper work on the identity management side, and expending HTTPD support beyond Keystone.</p>
<p>First is working on the <a title="PKI Blueprint" href="https://blueprints.launchpad.net/keystone/+spec/pki">Public Key Infrastructure (PKI) alternative to the Keystone Token architecture. </a>In addition to implementing that blueprint,  I have agreed to work with <a href="https://launchpad.net/~guang-yee">gyee</a> and <a href="https://launchpad.net/~liemmn">liemmn</a> on making sure that the PKI work and the<a href="https://blueprints.launchpad.net/keystone/+spec/access-key-authentication"> Key based authentication</a> they are working on fit into an understandable narrative about the options available in Openstack.</p>
<p>Of course,  my PKI work assumes web server support for PKI,  which, shortest path, is <a href="http://adam.younglogic.com/2012/04/keystone-httpd/">using HTTPD</a>.  There is  code from that example that I need to review and commit.  In order for it to be usable,  I need to set up and run a proof of concept system where Glance, Nova and Horizon all use Keystone  from HTTPD.</p>
<p>Once I&#8217;ve made that work,  I need to add support to <a href="http://devstack.org/" target="_blank">devstack</a> for it.</p>
<p>A follow on set of tasks will involve HTTPD-ifying  Nova and Glance.  To prep to site for this work,  we are trying to establish a n <a href="http://wiki.openstack.org/URLs" target="_blank">URL naming scheme for Openstack</a>.</p>
<p>While testing the EPEL packages of Openstack, I noticed that we lacked support for the VNC viewer <a href="https://github.com/kanaka/noVNC" target="_blank">noVNC</a>.  I am working with <a href="https://launchpad.net/~sleepsonthefloor" target="_blank">Anthony Young</a> (no relation to me) to come up with a supportable packing format that will be accepted by the Debian and Fedora packaging standards.</p>
<p>Longer term,  I want to be able to serve the noVNC javascript from Apache HTTPD, and talk back to HTTPD as well.  There are two alternatives here:</p>
<ol>
<li>Use an <a title="Apache Websockets" href="https://github.com/disconnect/apache-websocket" target="_blank">Apache Websockets</a> module and do it all in native code</li>
<li>Add Websockets support to mod_wsgi.</li>
</ol>
<p>The <a href="http://code.google.com/p/pywebsocket/" target="_blank">Google code approach uses mod_python</a>. However, mod_python is not actively maintained, so I think this code is not going to work long haul. Making it work in <a href="http://www.mailinglistarchive.com/html/modwsgi@googlegroups.com/2010-04/msg00173.html" target="_blank">mod_wsgi has hurdles to overcome</a>.  This leads me to favor the native approach as of now.  I have the Apache websocket module built as an RPM, and will continue toward integrating the VNC proxy in C as an additional module.</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.younglogic.com/2012/05/my-openstack-tasks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Array of Parameter Names in Java</title>
		<link>http://adam.younglogic.com/2012/04/array-param-names/</link>
		<comments>http://adam.younglogic.com/2012/04/array-param-names/#comments</comments>
		<pubDate>Mon, 09 Apr 2012 01:44:13 +0000</pubDate>
		<dc:creator>Adam Young</dc:creator>
				<category><![CDATA[IofC]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://adam.younglogic.com/?p=2092</guid>
		<description><![CDATA[My last post suggested an extension to the Java language that I think will be quite helpful. Until such a feature exists, we can fake it by using annotations. I created an annotation with a processor that creates a new &#8230; <a href="http://adam.younglogic.com/2012/04/array-param-names/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://adam.younglogic.com/2012/04/parameter-names-in-java/"> My last post suggested an extension to the Java language</a> that I think will be quite helpful.  Until such a feature exists,  we can fake it by using annotations.<br />
<span id="more-2092"></span></p>
<p>I created an annotation with a processor that creates a new class, one the contains a single static instance of an array of the parameter names from the constructor.</p>
<p>All code on this page released under the same license as the OpenJDK Libraries: GPL with the classpath exception.</p>
<p>First, the annotation itself.</p>
<pre class="brush:java">
package com.younglogic.annote;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.CONSTRUCTOR)
@Retention(RetentionPolicy.RUNTIME)
public @interface NamedParameters {

}
</pre>
<p>Next the annotation processor.  This uses the javac API,  which really should become part of the Base Java platform.  In order to compile I added <em>/usr/lib/jvm/java-1.7.0/lib/tools.jar</em>  to the classpath.</p>
<pre class="brush:java">
package com.younglogic.annote;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;

import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;

@SupportedAnnotationTypes(value = { "com.younglogic.annote.NamedParameters" })
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class NamedParametersAnnotationProcessor extends AbstractProcessor {

	@Override
	public boolean process(Set<? extends TypeElement> annotations,
			RoundEnvironment roundEnv) {
		for (TypeElement element : annotations) {
			for (Element constructor : roundEnv
					.getElementsAnnotatedWith(element)) {

				ClassSymbol classSymbol = (ClassSymbol) constructor
						.getEnclosingElement();
				PackageElement packageElement = (PackageElement) classSymbol
						.getEnclosingElement();

				JavaFileObject jfo;
				try {
					jfo = processingEnv.getFiler().createSourceFile(
							classSymbol.getQualifiedName() + "ParameterNames");
					BufferedWriter bw = new BufferedWriter(jfo.openWriter());
					bw.append("package ");
					bw.append(packageElement.getQualifiedName());
					bw.append(";");
					bw.newLine();
					bw.newLine();
					bw.append("public class " + classSymbol.getSimpleName()
							+ "ParameterNames {");
					bw.newLine();
					bw.append("    static String[] instance = {");
					MethodSymbol symbol = (MethodSymbol) constructor;
					int i = 0;
					for (VarSymbol param : symbol.getParameters()) {
						if (i++ > 0) {
							bw.append(",");
						}
						bw.newLine();
						bw.append("            \"" + param.name + "\"");
					}
					bw.newLine();
					bw.append("        };");
					bw.newLine();
					bw.append("    }");
					bw.newLine();
					bw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

		}
		return true;
	}
}
</pre>
<p>A sample class that uses this annotation.  Note that this class is immutable.</p>
<pre class="brush:java">
package com.younglogic.annotetest;

import com.younglogic.annote.NamedParameters;

public class SampleClass {

	final String s1;
	final String s2;
	final Integer i1;

	@NamedParameters
	public SampleClass(String s1, String s2, Integer i1) {
		super();
		this.s1 = s1;
		this.s2 = s2;
		this.i1 = i1;
	}

	@Override
	public String toString() {

		return "SampleClass values are: s1=" + s1 + ", s2=" + s2 + ", i1=" + i1.toString();
	}
}
</pre>
<p>Now add some parameters to the compiler.</p>
<p>-processor is the processor we want to explicitly call<br />
-processorpath  tells it where to find the new annotation.<br />
-s tells it  where to put the generated code</p>
<pre class="brush:bash">
 javac -cp ../NamedParameters/bin/  -processorpath ../NamedParameters/bin/ -s /tmp/generated/ -processor com.younglogic.annote.NamedParametersAnnotationProcessor   src/com/younglogic/annotetest/SampleClass.java
</pre>
<p>This will generate the source file: /tmp/generated/com/younglogic/annotetest/SampleClassParameterNames.java</p>
<pre class="brush:java">
package com.younglogic.annotetest;

public class SampleClassParameterNames {
    public static String[] instance = {
            "s1",
            "s2",
            "i1",
            "i2"
        };
    }
</pre>
<p>And compile it to /tmp/generated/com/younglogic/annotetest/SampleClassParameterNames.class</p>
<p>We can use that information to create new instances.  I have a file SampleClass.properties  with the values I want to use to create a new instance.</p>
<pre class="brush:java">
i1=5
i2=10
s1="first"
s2="next"
</pre>
<p>Read it in and populate a new instance dynamically:</p>
<pre class="brush:java">
package com.younglogic.annotetest;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;

public class UseParamNames {

	public static void main(String[] args) throws IOException,
			InstantiationException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
		Properties properties = new Properties();

		InputStream instream = UseParamNames.class
				.getResourceAsStream("SampleClass.properties");
		properties.load(instream);

		Constructor<?> c = getConstructor();

		Object[] initargs = new Object[SampleClassParameterNames.instance.length];
		int i = 0;
		for (String name : SampleClassParameterNames.instance) {
			Class[] argTypes = { String.class };

			String strvalue = properties.getProperty(name);
			String[] paramArgs = new String[1];
			paramArgs[0] = strvalue;

			initargs[i] = c.getParameterTypes()[i].getConstructor(argTypes)
					.newInstance(paramArgs);
			i++;

		}

		Object newInstance = c.newInstance(initargs);

		System.out.println(newInstance.toString());
	}

	private static Constructor<?> getConstructor() {
		for (Constructor<?> c : SampleClass.class.getConstructors()) {
			if (c.getAnnotations().length > 0) {
				return c;
			}

		}
		return null;
	}
}
</pre>
<p>Which, when run, produces the output:</p>
<pre class="brush:bash">
SampleClass values are: s1="first", s2="next", i1=5
</pre>
]]></content:encoded>
			<wfw:commentRss>http://adam.younglogic.com/2012/04/array-param-names/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Parameter Names in Java</title>
		<link>http://adam.younglogic.com/2012/04/parameter-names-in-java/</link>
		<comments>http://adam.younglogic.com/2012/04/parameter-names-in-java/#comments</comments>
		<pubDate>Thu, 05 Apr 2012 17:13:32 +0000</pubDate>
		<dc:creator>Adam Young</dc:creator>
				<category><![CDATA[IofC]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://adam.younglogic.com/?p=1990</guid>
		<description><![CDATA[There is a very small feature that could be added to Java in order to improve it significantly: Add names to the Parameter object in the Reflection API. When creating a new Object in Java,  the parameter list for the &#8230; <a href="http://adam.younglogic.com/2012/04/parameter-names-in-java/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>There is a very small feature that could be added to Java in order to improve it significantly: Add names to the Parameter object in the Reflection API.<br />
<span id="more-1990"></span></p>
<p>When creating a new Object in Java,  the parameter list for the constructor or factory provides the contract.  Unfortunately,  a key element of this contract is missing at run rime when it is needed most.  If a constructor takes multiple values of the same type,  the only way to distinguish between them are the names of the parameters.  For example,  the JDBC API to create a new connection takes three parameters: the username and password to use for the connection authentication and authorization, and the URL of the Datasource.  <a title="DriverManager.getConnection(java.lang.String, java.lang.String,java.lang.String)" href="docs.oracle.com/javase/6/docs/api/java/sql/DriverManager.html#getConnection(java.lang.String, java.lang.String,java.lang.String)">However, all three values are strings.</a> In order to distinguish between them,  the user needs to know the order of the parameters:  is it URL first or UserID first?  </p>
<p>Building a new object from a persisted dictionary is common enough that there is a different API as well that takes a<a title="DriverManager.getConnection(java.lang.String,java.util.Properties)" href="http://docs.oracle.com/javase/6/docs/api/java/sql/DriverManager.html#getConnection%28java.lang.String,%20java.util.Properties%29"> Properties object</a>.  This variation loses all documentation about what is required to authenticate a connection: username and password.  Since the format of the URL is also Driver specific,  the user is thus relegated to digging through the documentation to figure out how to correctly create a Connection.  However, reading the documentation is not an option for an automated tool.</p>
<p>What Java lacks is a standardized and automated way to map a key-value pair collection to a function.  The mechanism should look like this.</p>
<pre class="brush:java">
private static Object createInstanceFromProperties(Method method, Properties properties)
throws InstantiationException, IllegalAccessException,
       InvocationTargetException, NoSuchMethodException {
    //This is the new call.
    String[] paramNames = method.getParameterNames();
    //Spacing is due to limitation of web display for angle bracketed expressions.
    Class < ? > [] argsTypes = method.getParameterTypes();

    Object arguments[] = new Object[argsTypes.length];
    for (int i = 0; i < paramNames.length; i += 1) {
        String val = properties.getProperty(paramNames[i]);
        if (argsTypes[i] == java.lang.String.class) {
	    arguments[i] = val;
        }else{
            arguments[i] = argsTypes[i].getConstructor(java.lang.String.class).newInstance(val);
	}
    }
    return method.invoke(null, arguments);
}
</pre>
<p>A simple variation can work with a Constructor object instead of a Method object.  One assumption from the above code that should be explicit is that the framework using this call has enough information to determine which variation of the Method or Constructor to find.  </p>
<p>I wouldn't ordinarily implement an API like this as Parallel arrays,  but in this case,  it is the least impact on the existing API.  There is no "Parameter" object in the existing API.  </p>
<p>Since existing compiled classes would not have provided the array of names, one version of Java should be provided as a transitory step which will allow the JDK to return a Null if the class does not provide the appropriate strings.</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.younglogic.com/2012/04/parameter-names-in-java/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Openstack Keystone in HTTPD</title>
		<link>http://adam.younglogic.com/2012/04/keystone-httpd/</link>
		<comments>http://adam.younglogic.com/2012/04/keystone-httpd/#comments</comments>
		<pubDate>Wed, 04 Apr 2012 16:31:02 +0000</pubDate>
		<dc:creator>Adam Young</dc:creator>
				<category><![CDATA[Openstack]]></category>
		<category><![CDATA[PKI]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Sysadmin]]></category>

		<guid isPermaLink="false">http://adam.younglogic.com/?p=1905</guid>
		<description><![CDATA[After calling for Keystone to migrate to HTTPD, several people asked me if I would show how this can be done. Here are the steps. Update: in testing keystone, you need to change the username from demo to admin as &#8230; <a href="http://adam.younglogic.com/2012/04/keystone-httpd/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><A href="http://adam.younglogic.com/2012/03/keystone-shoul…o-apache-httpd/">After calling for Keystone to migrate to HTTPD,</a>  several people asked me if I would show how this can be done.  Here are the steps.</p>
<p><span id="more-1905"></span><br />
Update:  in testing keystone,  you need to change the username from <em>demo</em> to <em>admin</em> as per the export lines near the bottom of this page.</p>
<p>A prerequisite is to set up <a href="http://adam.younglogic.com/2012/03/ssl-nss-easy/" title="NSS SSL is Easy" target="_blank">NSS HTTPD SSL</a> support. We can use it in conjunction with Keystone to provide encrypted access for authentication and authorization.</p>
<p>I created a file to enable  wsgi:</p>
<p><em>/var/www/cgi-bin/keystone/keystone.py</em></p>
<pre class="brush:python">
import os
from keystone import config
from paste import deploy
from keystone.common import logging
from keystone.common import utils
from keystone.common import wsgi

LOG = logging.getLogger(__name__)
CONF = config.CONF
config_files = ['/opt/stack/keystone/etc/keystone.conf']
CONF(config_files=config_files)

conf = CONF.config_file[0]
#name = 'admin'
name = os.path.basename(__file__)

if CONF.debug:
    CONF.log_opt_values(logging.getLogger(CONF.prog), logging.DEBUG)

options = deploy.appconfig('config:%s' % CONF.config_file[0])

application = deploy.loadapp('config:%s' % conf, name=name)
</pre>
<p>And I hardlinked it:</p>
<pre class="brush:bash">
cd /var/www/cgi-bin/keystone/
ln  keystone.py admin
ln  keystone.py main
</pre>
<p>This is based on a Fedora devstack deployment,  which checks out the code in /opt/stack/keystone.  I ran against master from git,  which as of this writing should be the same as the next Essex RC.  I ran python setup.py install  with this,  which gave me the installed egg in</p>
<p><em>/usr/lib/python2.7/site-packages/keystone-2012.2-py2.7.egg. </em></p>
<p>Since eggs deployed this way are part of the default Python path, it is usable by WSGI applications in Apache.</p>
<p>To run against the Fedora RPMs,  the difference would be to read in the config file  <em>/etc/keystone/keystone.conf</em> instead.  </p>
<p>I&#8217;ve changed /etc/httpd/conf.d/keystone.conf to</p>
<pre class="brush:bash">
WSGIScriptAlias /main /var/www/cgi-bin/keystone/main
WSGIScriptAlias /admin /var/www/cgi-bin/keystone/admin

<Location "/main">
   NSSRequireSSL
</Location>

<Location "/admin">
   NSSRequireSSL
</Location>
</pre>
<p>and restarted httpd.  To test:<br />
<a href="http://adam.younglogic.com/wp-content/uploads/2012/04/keystone-ssl.png"><img src="http://adam.younglogic.com/wp-content/uploads/2012/04/keystone-ssl.png" alt="" title="keystone-ssl" width="879" height="797" class="alignleft size-full wp-image-2066" /></a></p>
<p>The most straightforward way to test Keystone is via the command line interface (CLI).  When running via devstack,  the normal approach is to source the environment file:</p>
<pre class="brush:bash">. openrc</pre>
<p>which pulls in the localrc.  This sets many values, including the URL to be used when the Keystone CLI talks to the server: OS_AUTH_URL.  Typically this is set as some variation on the local hostname and the port 5000.  It also sets the username to <em>demo</em>  To test HTTPD,   change this to:</p>
<pre class="brush:bash">
export OS_AUTH_URL=https://$HOSTNAME/admin/v2.0
export OS_USERNAME=admin
</pre>
<p>However, running the command line client gave an error:</p>
<pre class="brush:bash">
[ayoung@ayoungstack devstack]$ keystone user-list
No handlers could be found for logger "keystoneclient.client"
Invalid OpenStack Identity credentials
</pre>
<p>Looking in the access log,  I saw the token request was succeeding (returned 200) but the second request failed with unauthorized (401).</p>
<p>One difference between Eventlet and the Fedora build of HTTPD is that each request in HTTPD is handled by a separate process.  This is called prefork,  and you can test a given install by running</p>
<pre class="brush:bash">
[ayoung@ayoung keystone]$ httpd -l
Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c
</pre>
<p>To see the built in modules.  The default way that Keystone stores Tokens is by using a key value pair storage.  You see this in the keystone.conf file.</p>
<pre class="brush:bash">
[token]
driver = keystone.token.backends.kvs.Token
</pre>
<p>By changing this to the SQL store,  the tokens are now accessable by other processes,  including the ones that will handle follow on requests to Keystone.</p>
<pre class="brush:bash">
[token]
driver = keystone.token.backends.sql.Token
</pre>
<p>And now the keystone CLI works:</p>
<pre class="brush:bash">

[ayoung@ayoungstack devstack]$ keystone user-list
+----------------------------------+---------+--------------------+--------+
|                id                | enabled |       email        |  name  |
+----------------------------------+---------+--------------------+--------+
| 6d42897928974d469a4223302e6bae4a | True    | admin@example.com  | admin  |
| 72f2941c7e3e40b292d50bd8b1662899 | True    | demo@example.com   | demo   |
| 92556c2d36de4f46a0a9916d96d2e793 | True    | glance@example.com | glance |
| e452d5f649ed489c8b84b8192e781263 | True    | nova@example.com   | nova   |
+----------------------------------+---------+--------------------+--------+
</pre>
]]></content:encoded>
			<wfw:commentRss>http://adam.younglogic.com/2012/04/keystone-httpd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Client Certificates with mod_nss</title>
		<link>http://adam.younglogic.com/2012/03/client-certs-nss/</link>
		<comments>http://adam.younglogic.com/2012/03/client-certs-nss/#comments</comments>
		<pubDate>Fri, 30 Mar 2012 21:22:23 +0000</pubDate>
		<dc:creator>Adam Young</dc:creator>
				<category><![CDATA[Openstack]]></category>
		<category><![CDATA[PKI]]></category>
		<category><![CDATA[Sysadmin]]></category>

		<guid isPermaLink="false">http://adam.younglogic.com/?p=2036</guid>
		<description><![CDATA[Once server side certificates have been set up, setting up client side certificates requires some additional configuration, especially if you want to use them as the source of identity in your applications. First, the application needs the additional directive in &#8230; <a href="http://adam.younglogic.com/2012/03/client-certs-nss/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Once server side certificates have been set up,  setting up client side certificates requires some additional configuration, especially if you want to use them as the source of identity in your applications.</p>
<p><span id="more-2036"></span></p>
<p>First,  the application needs the additional  directive in its /etc/httpd/conf.d specific file.</p>
<pre class="brush:bash">
   NSSVerifyClient require
</pre>
<p>Did that work for you?  NO&#8230;me neither&#8230;</p>
<p>OK, so  actually, it was slightly more involved.  First, I had to figure out how to turn on NSS debugging. That is done by editing the file</p>
<p>/etc/httpd/conf.d/nss.conf </p>
<p>and setting the value for </p>
<pre class="brush:bash">
LogLevel debug
</pre>
<p>Once that worked,  I saw messages in /var/log/httpd/error_log that looked like:</p>
<pre class="brush:bash">
[Fri Mar 30 11:43:54 2012] [debug] nss_engine_kernel.c(309): Changed client verification type will force renegotiation
[Fri Mar 30 11:43:54 2012] [info] Requesting connection re-negotiation
[Fri Mar 30 11:43:54 2012] [debug] nss_engine_kernel.c(404): Performing full renegotiation: complete handshake protocol
[Fri Mar 30 11:43:54 2012] [debug] nss_engine_kernel.c(418): Re-negotation request failed: returned error -12176
</pre>
<p>So I enabled renegotiation.  Again, editing /etc/httpd/conf.d/nss.conf </p>
<pre class="brush:bash">
NSSRenegotiation on
NSSRequireSafeNegotiation on
</pre>
<p>And then client side certs worked for me.  They probably won&#8217;t work for you, though.</p>
<p><em>I cheated.</em></p>
<p>In between,  I set up a<a href="http://pki.fedoraproject.org/wiki/PKI_Main_Page" title="Dogtag PKI"> Dogtag PKI </a>instance,  generated a new server side certificate,  a client side certificate for my browser,  and installed the CA and Server side certificate in my web server. </p>
<p>I don&#8217;t think all of that was necessary.  </p>
<p>A variation would have been to generate a client side certificate and sign it with the self-sign CA key that my web server was already using.  The bottom line is that the browser and the server need to <em>both trust the CAs used</em> for the client and server certs.</p>
<p>Ok,  so we&#8217;ve established a secure channel.  This doesn&#8217;t mean much if we don&#8217;t know who the user is at the application level.  The NSS layer follows the SSL approach of using the option: <strong>FakeBasicAuth</strong> to pass information from the Certificate through to the application.  I uncommented the line: </p>
<pre class="brush:bash">
NSSOptions +FakeBasicAuth +ExportCertData +CompatEnvVars +StrictRequire
</pre>
<p>You also need to tell NSS which value from the certificate should be passed as the user.  In my case,  it is the Subject:uid value,  so I configured mine as:</p>
<pre class="brush:bash">
NSSUserName SSL_CLIENT_S_DN_UID
</pre>
<p>The overall difference in the nss.conf file is:</p>
<pre class="brush:diff">
--- /etc/httpd/conf.d/nss.conf.orig	2012-03-29 12:59:06.319470425 -0400
+++ /etc/httpd/conf.d/nss.conf	2012-03-30 16:21:24.836124822 -0400
@@ -17,7 +17,7 @@
 # Note: Configurations that use IPv6 but not IPv4-mapped addresses need two
 #       Listen directives: "Listen [::]:8443" and "Listen 0.0.0.0:443"
 #
-Listen 8443
+Listen 443

 ##
 ##  SSL Global Context
@@ -71,17 +71,17 @@
 #
 # Only renegotiate if the peer's hello bears the TLS renegotiation_info
 # extension. Default off.
-NSSRenegotiation off
+NSSRenegotiation on

 # Peer must send Signaling Cipher Suite Value (SCSV) or
 # Renegotiation Info (RI) extension in ALL handshakes.  Default: off
-NSSRequireSafeNegotiation off
+NSSRequireSafeNegotiation on

 ##
 ## SSL Virtual Host Context
 ##

-<VirtualHost _default_:8443>
+<VirtualHost _default_:443>

 #   General setup for the virtual host
 #DocumentRoot "/etc/httpd/htdocs"
@@ -92,7 +92,7 @@
 # LogLevel is not inherited from httpd.conf.
 ErrorLog /etc/httpd/logs/error_log
 TransferLog /etc/httpd/logs/access_log
-LogLevel warn
+LogLevel debug

 #   SSL Engine Switch:
 #   Enable/Disable SSL for this virtual host.
@@ -198,7 +198,8 @@
 #   o OptRenegotiate:
 #     This enables optimized SSL connection renegotiation handling when SSL
 #     directives are used in per-directory context.
-#NSSOptions +FakeBasicAuth +ExportCertData +CompatEnvVars +StrictRequire
+NSSOptions +FakeBasicAuth +ExportCertData +CompatEnvVars +StrictRequire
+NSSUserName SSL_CLIENT_S_DN_UID
 <Files ~ "\.(cgi|shtml|phtml|php3?)$">
     NSSOptions +StdEnvVars
 </Files>
</pre>
<p>Now a little bit of Python/WSGI specifics<br />
For my WSGI application,  I add in a value that says &#8220;pass on the authentication info to the application&#8221;</p>
<pre class="brush:bash">
WSGIPassAuthorization On
</pre>
<p>Then the WSGI app can access the value  via: </p>
<pre class="brush:bash">
class Application(BaseApplication):
    @webob.dec.wsgify
    def __call__(self, req):
    context['remote_user'] = req.environ.get('REMOTE_USER')
</pre>
<p>Here is what my file /etc/httpd/conf.d/keystone.conf  looks like to protect the suburl &#8220;main&#8221;:</p>
<pre class="brush:plain">
WSGIScriptAlias /main /var/www/wsgi/httpdmain.py
WSGIScriptAlias /admin /var/www/wsgi/httpdadmin.py

< Location "/main" >
   NSSRequireSSL
   NSSVerifyClient require
   WSGIPassAuthorization On
< / Location >
</pre>
]]></content:encoded>
			<wfw:commentRss>http://adam.younglogic.com/2012/03/client-certs-nss/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Setting up SSL with NSS is easier than you think</title>
		<link>http://adam.younglogic.com/2012/03/ssl-nss-easy/</link>
		<comments>http://adam.younglogic.com/2012/03/ssl-nss-easy/#comments</comments>
		<pubDate>Fri, 30 Mar 2012 17:50:30 +0000</pubDate>
		<dc:creator>Adam Young</dc:creator>
				<category><![CDATA[PKI]]></category>
		<category><![CDATA[Sysadmin]]></category>

		<guid isPermaLink="false">http://adam.younglogic.com/?p=1975</guid>
		<description><![CDATA[At least, it is on Fedora 16 sudo yum install mod_nss /etc/httpd/alias/ is populated already with ca and server cert self signed /etc/httpd/conf.d/nss.conf already exists change 8443 to 443 in two places --- /etc/httpd/conf.d/nss.conf.orig 2012-03-29 12:59:06.319470425 -0400 +++ /etc/httpd/conf.d/nss.conf 2012-03-29 &#8230; <a href="http://adam.younglogic.com/2012/03/ssl-nss-easy/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>At least, it is on Fedora 16</p>
<pre class="brush:bash">
sudo yum install mod_nss
</pre>
<p>/etc/httpd/alias/ is populated already with ca and server cert self signed<br />
/etc/httpd/conf.d/nss.conf  already exists<br />
change 8443 to 443 in two places </p>
<pre class="brush:diff">
--- /etc/httpd/conf.d/nss.conf.orig	2012-03-29 12:59:06.319470425 -0400
+++ /etc/httpd/conf.d/nss.conf	2012-03-29 12:19:38.862721465 -0400
@@ -17,7 +17,7 @@
 # Note: Configurations that use IPv6 but not IPv4-mapped addresses need two
 #       Listen directives: "Listen [::]:8443" and "Listen 0.0.0.0:443"
 #
-Listen 8443
+Listen 443

 ##
 ##  SSL Global Context
@@ -81,7 +81,7 @@
 ## SSL Virtual Host Context
 ##

-<VirtualHost _default_:8443>
+<VirtualHost _default_:443>

 #   General setup for the virtual host
 #DocumentRoot "/etc/httpd/htdocs"
</pre>
<p>Make sure your firewall is open on the HTTPS port.  Add the following line in /etc/sysconfig/iptables</p>
<pre class="brush:bash">
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
</pre>
<p>before the statement</p>
<pre class="brush:bash">
-A INPUT -j REJECT --reject-with icmp-host-prohibited
</pre>
<p>and restart the services</p>
<pre class="brush:bash">
sudo systemctl restart iptables.service
sudo systemctl restart httpd.service
</pre>
<p>The <a href="http://directory.fedoraproject.org/wiki/Mod_nss#Documentation"> documentation </a> provides a lot more detail.  Almost all of these steps are performed by the RPM install on F16 and later.</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.younglogic.com/2012/03/ssl-nss-easy/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Shared Nothing Diskless Boot</title>
		<link>http://adam.younglogic.com/2012/03/shared-nothing-diskless-boot/</link>
		<comments>http://adam.younglogic.com/2012/03/shared-nothing-diskless-boot/#comments</comments>
		<pubDate>Wed, 28 Mar 2012 01:07:15 +0000</pubDate>
		<dc:creator>Adam Young</dc:creator>
				<category><![CDATA[shell]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Sysadmin]]></category>

		<guid isPermaLink="false">http://adam.younglogic.com/?p=2000</guid>
		<description><![CDATA[It is possible to run a computer with no persistent storage for its root file system other than a single image downloaded an held in RAM. The computer does not needs a local disk. The computer also does not need &#8230; <a href="http://adam.younglogic.com/2012/03/shared-nothing-diskless-boot/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>It is possible to run a computer with no persistent storage for its root file system other than a single image downloaded an held in RAM. The computer does not needs a local disk. The computer also does not need a SAN or NAS device for the Root File system.</p>
<p>There are numerous uses for this style of booting.  A short list:</p>
<ul>
<li>Debugging the installation processes of software packages</li>
<li>Running computationally intensive tasks on a large array of nodes</li>
<li>Inventorying the hardware no new servers</li>
<li>Deploying a light management framework for virtualization hypervisors</li>
</ul>
<p>Here is a brief overview of the pieces needed to set this up for testing purposes on a workstation running KVM.</p>
<p><span id="more-2000"></span></p>
<ul>
<li>Configure a local network for PXE traffic</li>
<li>Install a machine to server as the PXE server</li>
<li>Install and Configure DHCPD</li>
<li>Install and Configure TFTP</li>
<li>create a rootfs</li>
<li>Install HTTPD</li>
<li>get a boot image</li>
<li>PXE Boot a Blank VM</li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>The first piece is done on the workstation itself, and is just overhead for doing this ins a completely virtualized environment.  This is the analogue of using a private secured backbone for administrative backbone when using physical machines.  Configuring the network used to take editing the Network XML file, but now you can deselect the DHCP checkbox in virt-manager when creating a new network.  Here is what mine generated in /var/lib/libvirt/network/nodhcp.xml.</p>
<pre class="brush:xml">

<network>
  <name>nodhcp</name>
  <uuid>ec819c42-b4b0-1577-363e-1c5918a3ee29</uuid>
  <bridge name='virbr2' stp='on' delay='0' />
  <mac address='52:54:00:FC:2F:62'/>
  <ip address='172.33.22.1' netmask='255.255.255.0'>
  </ip>
</network>
</pre>
<p>You could save that in /root and do </p>
<pre class="brush:bash"> sudo virsh network-create /root/nodhcp.xml</pre>
<p>This one has a bridge defined, which is probably not what you would want for your server, as this network should not see the outside world.  Still the device is useful if you want to run wireshark on it to debug booting issues.</p>
<p>Create the server as a VM, and provide it Network interface on both a publicly accessible as well as the Private network defined above.  Install Fedora (I used F17 Alpha) as per normal.</p>
<p>Install the Server pieces</p>
<pre class="brush:bash">
yum install syslinux tftp-server  dhcp  dracut-network  httpd httpd-tools apr apr-util apr-util-lda
</pre>
<p>Configure DHCPD by editing /etc/dhcp/dhcpd.conf </p>
<pre class="brush:c">
allow booting;
allow bootp;

subnet 172.22.33.0 netmask 255.255.255.0 {
        option routers                  172.22.33.1;
        option subnet-mask              255.255.255.0;
        option domain-search              "younglogic.com";
        option domain-name-servers       172.22.33.1;
        option time-offset              -18000;     # Eastern Standard Time
        range 172.22.33.100 172.22.33.140;
}

class "pxeclients" {
   match if substring(option vendor-class-identifier, 0, 9) = "PXEClient";
   next-server server-ip;
   filename "pxelinux.0";
</pre>
<p>Set up TFTP.</p>
<p>edit /etc/xinetd.d/tftp and set</p>
<pre class="brush:bash">
	disable			= no
</pre>
<p>Copy over the Kernel</p>
<pre class="brush:bash">
cp /boot/vmlinuz-3.3.0-0.rc6.git0.2.fc17.x86_64 /var/lib/tftpboot/vmlinuz-3.3.0-0.rc6.git0.2.fc17.x86_64
</pre>
<p><a href="https://dracut.wiki.kernel.org/">Dracut</a> is a great tool for people that need to control the boot procedure of their machines.  It has a module called <strong>Livenet</strong> that we use to specifying that the root file system should be downloaded an unpacked in a directory.  In order for that to work, we need the dracut-network package specified on the yum line above.  THen,  we need to generate a new initial ramdisk (initrd) with the livenet module enabled.  </p>
<pre class="brush:bash">
dracut -v  --force --add "livenet"  /var/lib/tftpboot/initramfs-kernel-3.3.0-0.rc6.git0.2.fc17.x86_64.img 3.3.0-0.rc6.git0.2.fc17.x86_64
</pre>
<p>Syslinux is our boot loader.  Syslinux is more than a tool to run an installer (although it does that quite well).  Here, it is a program that is configured much as for a kickstart,  but it will instead switch to running the kernel instead of Anaconda.</p>
<pre class="brush:bash">
cp  /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot
mkdir /var/lib/tftpboot/pxelinux.cfg/
</pre>
<p>The configuration for syslinux is in /var/lib/tftpboot/pxelinux.cfg/default and looks like this</p>
<pre class="brush:bash">
default f17

serial --unit=0 --speed=9600
terminal --timeout=5 serial console

label f17
  kernel vmlinuz-3.3.0-0.rc6.git0.2.fc17.x86_64
  append initrd=initramfs-kernel-3.3.0-0.rc6.git0.2.fc17.x86_64.img console=tty0  rd.shell rd.debug root=live:http://172.22.33.2/squashfs.img   rw
</pre>
<p>The most interesting value here is <strong>root=live:http://172.22.33.2/squashfs.img</strong> which is what activates the Dracut module in the initrd to download the rootfs via http and expand it into the new root directory.</p>
<p>I know that a couple of these values are incorrect, and I will update when I have them straight, but this will work.</p>
<p>Once everything is in place, you need to make sure SELinux is happy.  Otherwise, the Kernel will deny the tftp network service access to the files it needs to serve.  Of course, you could always disable SELinux,  but <a href="http://wiki.centos.org/HowTos/SELinux"> lets try to do things right</a> To see what the SELinux context for the newly copied file is: </p>
<pre class="brush:bash">
ls -Z /var/lib/tftpboot/vmlinuz-3.3.0-0.rc6.git0.2.fc17.x86_64
rwxr-xr-x. root root unconfined_u:object_r:tftpdir_rw_t:s0 /var/lib/tftpboot/vmlinuz-3.3.0-0.rc6.git0.2.fc17.x86_64
</pre>
<p><a href="http://userspace.selinuxproject.org/trac/wiki/SelinuxTools">To see what it should be:</a></p>
<pre class="brush:bash">
[root@f17stack ~]# matchpathcon /var/lib/tftpboot/
/var/lib/tftpboot	system_u:object_r:tftpdir_rw_t:s0
</pre>
<p>To set the whole directory to the correct context</p>
<pre class="brush:bash">
 chcon -Rv --type=tftpdir_rw_t  --user=system_u  /var/lib/tftpboot/
</pre>
<p>There is probably a more correct way to do this,  something along the lines of </p>
<pre class="brush:bash">
restorecon -R -v /var/lib/tftpboot/
</pre>
<p>But that doesn&#8217;t seem to set the user.</p>
<p>At this point you can restart both services.  Make sure that dhcpd runs at machine reboot as well.</p>
<pre class="brush:bash">
/bin/systemctl enable  dhcpd.service
/bin/systemctl restart xinetd.service
/bin/systemctl restart dhcpd.service
</pre>
<p>To test that things are running correctly: </p>
<pre class="brush:bash">
[root@f17stack tmp]# cd /tmp
[root@f17stack tmp]# getenforce
Enforcing
[root@f17stack tmp]# tftp localhost -c get initramfs-kernel-3.3.0-0.rc6.git0.2.fc17.x86_64.img
[root@f17stack tmp]# ls initramfs-kernel-3.3.0-0.rc6.git0.2.fc17.x86_64.img
initramfs-kernel-3.3.0-0.rc6.git0.2.fc17.x86_64.img
</pre>
<p>Make sure Apache is running and will run on boot:</p>
<pre class="brush:bash">
[root@f17stack tmp]# systemctl enable  httpd.service
[root@f17stack tmp]# systemctl start httpd.service
</pre>
<p>The final step is to setup a bootable image.  In this case,  we use the same thing that the live CD uses, which is packaged inside of a <a href="http://tldp.org/HOWTO/SquashFS-HOWTO/creatingandusing.html">squashfs</a> image.</p>
<p>I did this on my desktop to keep from having to have too big a file on my Server VM.  As it is, this is still  close to a 588MB image.</p>
<pre class="brush:bash">
sudo mount -o loop  ~/Downloads/Fedora-16-x86_64-Live-Desktop.iso /mnt
scp /mnt/LiveOS/squashfs.img root@f17stack.ayoung.boston.devel.redhat.com:/var/www/html
</pre>
<p>And again, on the server, lets check SELinux</p>
<pre class="brush:bash">
[root@f17stack tmp]# ls -Z /var/www/html/
f16/          index.html    squashfs.img
[root@f17stack tmp]# ls -Z /var/www/html/squashfs.img
-r--r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/squashfs.img
</pre>
<p>And make SELinux Happy:</p>
<pre class="brush:bash">
chcon -Rv --type=httpd_sys_content_t  --user=system_u  /var/www/html/
</pre>
<p>I have to admit,  I had already gotten the system to relable the file by the time I tested this,  I suspect upon a reboot, so this last step might not be necessary.</p>
<p>Now,  open the firewall to let dhcp, tftp, and http  traffic through.  This can be done via the following rules added to /etc/sysconfig/iptables</p>
<pre class="brush:bash">
-A INPUT -m state --state NEW -m tcp -p tcp --dport 68 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 68 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 69 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 69 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
</pre>
<p>And restarting iptables:</p>
<pre class="brush:bash">
systemctl start iptables.service
</pre>
<p>Now Boot the second VM.  If all goes well, it will Get its IP address:</p>
<p><a href="http://adam.younglogic.com/wp-content/uploads/2012/03/Screenshot-at-2012-03-27-170123.png"><img src="http://adam.younglogic.com/wp-content/uploads/2012/03/Screenshot-at-2012-03-27-170123-300x217.png" alt="" title="Screenshot at 2012-03-27 17:01:23" width="300" height="217" class="alignleft size-medium wp-image-2013" /></a></p>
<p>There will likely be a delay as it downloads the 588 install image:</p>
<p><a href="http://adam.younglogic.com/wp-content/uploads/2012/03/Screenshot-at-2012-03-27-170138.png"><img src="http://adam.younglogic.com/wp-content/uploads/2012/03/Screenshot-at-2012-03-27-170138-300x217.png" alt="" title="Screenshot at 2012-03-27 17:01:38" width="300" height="217" class="alignleft size-medium wp-image-2014" /></a></p>
<p>And when it is done,  you are at Firstboot:</p>
<p><a href="http://adam.younglogic.com/wp-content/uploads/2012/03/Screenshot-at-2012-03-27-170452.png"><img src="http://adam.younglogic.com/wp-content/uploads/2012/03/Screenshot-at-2012-03-27-170452-300x217.png" alt="" title="Screenshot at 2012-03-27 17:04:52" width="300" height="217" class="alignleft size-medium wp-image-2017" /></a></p>
<p>Thanks to Will Woods for cluing me in about squashfs and livenet, Harald Hoyer for general Dracut help, and  Ray Strode for help with debugging why my console wouldn&#8217;t echo.</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.younglogic.com/2012/03/shared-nothing-diskless-boot/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

