r509-ca-http 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/README.md +122 -0
  2. data/Rakefile +38 -0
  3. data/doc/R509.html +117 -0
  4. data/doc/R509/CertificateAuthority.html +117 -0
  5. data/doc/R509/CertificateAuthority/Http.html +131 -0
  6. data/doc/R509/CertificateAuthority/Http/Factory.html +115 -0
  7. data/doc/R509/CertificateAuthority/Http/Factory/CsrFactory.html +189 -0
  8. data/doc/R509/CertificateAuthority/Http/Factory/SpkiFactory.html +189 -0
  9. data/doc/R509/CertificateAuthority/Http/Server.html +133 -0
  10. data/doc/R509/CertificateAuthority/Http/SubjectParser.html +265 -0
  11. data/doc/R509/CertificateAuthority/Http/ValidityPeriodConverter.html +207 -0
  12. data/doc/_index.html +206 -0
  13. data/doc/class_list.html +53 -0
  14. data/doc/css/common.css +1 -0
  15. data/doc/css/full_list.css +57 -0
  16. data/doc/css/style.css +328 -0
  17. data/doc/file.README.html +209 -0
  18. data/doc/file_list.html +55 -0
  19. data/doc/frames.html +28 -0
  20. data/doc/index.html +209 -0
  21. data/doc/js/app.js +214 -0
  22. data/doc/js/full_list.js +173 -0
  23. data/doc/js/jquery.js +4 -0
  24. data/doc/method_list.html +92 -0
  25. data/doc/top-level-namespace.html +112 -0
  26. data/lib/r509/certificateauthority/http/factory.rb +15 -0
  27. data/lib/r509/certificateauthority/http/server.rb +237 -0
  28. data/lib/r509/certificateauthority/http/subjectparser.rb +33 -0
  29. data/lib/r509/certificateauthority/http/validityperiodconverter.rb +16 -0
  30. data/lib/r509/certificateauthority/http/version.rb +7 -0
  31. data/lib/r509/certificateauthority/http/views/test_issue.erb +85 -0
  32. data/lib/r509/certificateauthority/http/views/test_revoke.erb +31 -0
  33. data/lib/r509/certificateauthority/http/views/test_unrevoke.erb +26 -0
  34. data/spec/fixtures/test_ca.cer +22 -0
  35. data/spec/fixtures/test_ca.key +28 -0
  36. data/spec/fixtures/test_config.yaml +18 -0
  37. data/spec/http_spec.rb +250 -0
  38. data/spec/spec_helper.rb +22 -0
  39. data/spec/subject_parser_spec.rb +51 -0
  40. data/spec/validity_period_converter_spec.rb +79 -0
  41. metadata +165 -0
@@ -0,0 +1,209 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII" />
6
+ <title>
7
+ File: README
8
+
9
+ &mdash; Documentation by YARD 0.8.3
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ hasFrames = window.top.frames.main ? true : false;
19
+ relpath = '';
20
+ framesUrl = "frames.html#!" + escape(window.location.href);
21
+ </script>
22
+
23
+
24
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
25
+
26
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
27
+
28
+
29
+ </head>
30
+ <body>
31
+ <div id="header">
32
+ <div id="menu">
33
+
34
+ <a href="_index.html">Index</a> &raquo;
35
+ <span class="title">File: README</span>
36
+
37
+
38
+ <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
39
+ </div>
40
+
41
+ <div id="search">
42
+
43
+ <a class="full_list_link" id="class_list_link"
44
+ href="class_list.html">
45
+ Class List
46
+ </a>
47
+
48
+ <a class="full_list_link" id="method_list_link"
49
+ href="method_list.html">
50
+ Method List
51
+ </a>
52
+
53
+ <a class="full_list_link" id="file_list_link"
54
+ href="file_list.html">
55
+ File List
56
+ </a>
57
+
58
+ </div>
59
+ <div class="clear"></div>
60
+ </div>
61
+
62
+ <iframe id="search_frame"></iframe>
63
+
64
+ <div id="content"><div id='filecontents'><h1>r509-ca-http</h1>
65
+
66
+ <p>r509-ca-http is an HTTP server that runs a certificate authority, for signing SSL certificates. It supports issuance and revocation, and is intended to be part of a complete certificate authority for use in production environments.</p>
67
+
68
+ <h2>Requirements/Installation</h2>
69
+
70
+ <p>You need r509 and sinatra. For development/tests you need rack-test and rspec.</p>
71
+
72
+ <h2>API</h2>
73
+
74
+ <h3>GET /1/crl/:ca/get</h3>
75
+
76
+ <p>Get the most recently generate CRL for the given <code>:ca</code>.</p>
77
+
78
+ <p>A new CRL is generated when a certificate is revoked or unrevoked, or if you explicitly generate it.</p>
79
+
80
+ <h3>GET /1/crl/:ca/generate</h3>
81
+
82
+ <p>Explicitly generate and get a new CRL for the given <code>:ca</code>.</p>
83
+
84
+ <h3>POST /1/certificate/issue</h3>
85
+
86
+ <p>Issue a certificate.</p>
87
+
88
+ <p>Required POST parameters:</p>
89
+
90
+ <ul>
91
+ <li>ca</li>
92
+ <li>profile</li>
93
+ <li>validityPeriod (in days)</li>
94
+ <li>csr (or spki)</li>
95
+ <li>subject</li>
96
+ </ul>
97
+
98
+ <p>The subject is provided like so:</p>
99
+
100
+ <pre class="code ruby"><code><span class='id identifier rubyid_subject'>subject</span><span class='lbracket'>[</span><span class='const'>CN</span><span class='rbracket'>]</span><span class='op'>=</span><span class='id identifier rubyid_domain'>domain</span><span class='period'>.</span><span class='id identifier rubyid_com'>com</span><span class='op'>&amp;</span><span class='id identifier rubyid_subject'>subject</span><span class='lbracket'>[</span><span class='const'>O</span><span class='rbracket'>]</span><span class='op'>=</span><span class='id identifier rubyid_orgname'>orgname</span><span class='op'>&amp;</span><span class='id identifier rubyid_subject'>subject</span><span class='lbracket'>[</span><span class='const'>L</span><span class='rbracket'>]</span><span class='op'>=</span><span class='id identifier rubyid_locality'>locality</span>
101
+ </code></pre>
102
+
103
+ <p>Optional POST parameters:</p>
104
+
105
+ <ul>
106
+ <li>extensions[subjectAlternativeName]</li>
107
+ </ul>
108
+
109
+ <p>SAN names are provided like so:</p>
110
+
111
+ <pre class="code ruby"><code><span class='id identifier rubyid_extensions'>extensions</span><span class='lbracket'>[</span><span class='id identifier rubyid_subjectAlternativeName'>subjectAlternativeName</span><span class='rbracket'>]</span><span class='lbracket'>[</span><span class='rbracket'>]</span><span class='op'>=</span><span class='id identifier rubyid_domain1'>domain1</span><span class='period'>.</span><span class='id identifier rubyid_com'>com</span><span class='op'>&amp;</span><span class='id identifier rubyid_extensions'>extensions</span><span class='lbracket'>[</span><span class='id identifier rubyid_subjectAlternativeName'>subjectAlternativeName</span><span class='rbracket'>]</span><span class='lbracket'>[</span><span class='rbracket'>]</span><span class='op'>=</span><span class='id identifier rubyid_domain2'>domain2</span><span class='period'>.</span><span class='id identifier rubyid_com'>com</span>
112
+ </code></pre>
113
+
114
+ <p>The issue method will return the PEM text of the issued certificate.</p>
115
+
116
+ <h3>POST /1/certificate/revoke</h3>
117
+
118
+ <p>Revoke a certificate.</p>
119
+
120
+ <p>Required POST parameters:</p>
121
+
122
+ <ul>
123
+ <li>ca</li>
124
+ <li>serial</li>
125
+ </ul>
126
+
127
+ <p>Optional POST parameters:</p>
128
+
129
+ <ul>
130
+ <li>reason (must be an integer, if it&#39;s not provided it defaults to 0)</li>
131
+ </ul>
132
+
133
+ <p>The revoke method returns the newly generated CRL, after revocation.</p>
134
+
135
+ <h3>POST /1/certificate/unrevoke</h3>
136
+
137
+ <p>Unrevoke a certificate. (IE, remove it from the CRL and return its OCSP status to valid.)</p>
138
+
139
+ <p>Required POST parameters:</p>
140
+
141
+ <ul>
142
+ <li>ca</li>
143
+ <li>serial</li>
144
+ </ul>
145
+
146
+ <p>The unrevoke method returns the newly generated CRL, after the certificate was removed from it.</p>
147
+
148
+ <h2>Helper pages</h2>
149
+
150
+ <p>These pages are present on the server, for you to work with the CA with a basic web interface. You should <em>not</em> expose these endpoints to anyone.</p>
151
+
152
+ <ul>
153
+ <li><p>/test/certificate/issue</p></li>
154
+ <li><p>/test/certificate/revoke</p></li>
155
+ <li><p>/test/certificate/unrevoke</p></li>
156
+ </ul>
157
+
158
+ <h2>certificate_authorities (config.yaml)</h2>
159
+
160
+ <p>You use the <code>config.yaml</code> file to specify information about your certificate authority. You can operate multiple certificate authorities, each of which can have multiple profiles, with one instance of r509-ca-http.</p>
161
+
162
+ <p>Information about how to construct the YAML can be found at <a href="https://github.com/reaperhulk/r509#config">the official r509 documentation</a>.</p>
163
+
164
+ <h2>Middleware (config.ru)</h2>
165
+
166
+ <p>Running r509-ca-http will let you issue and revoke certificates. But that&#39;s not everything you need to do, if you&#39;re going to run a CA. You&#39;re going to need information about validity, and you may want to save a record of issued certificates to the filesystem.</p>
167
+
168
+ <p>For that, we&#39;ve created a few pieces of Rack middleware for your use.</p>
169
+
170
+ <ul>
171
+ <li><a href="https://github.com/sirsean/r509-middleware-validity">r509-middleware-validity</a></li>
172
+ <li><a href="https://github.com/sirsean/r509-middleware-certwriter">r509-middleware-certwriter</a></li>
173
+ </ul>
174
+
175
+ <p>After installing one or both of them, you&#39;ll have to edit your <code>config.ru`` and/or</code>config.yaml``` files.</p>
176
+
177
+ <h2>Rake tasks</h2>
178
+
179
+ <p>There are a few things you can do with Rake.</p>
180
+
181
+ <p><code>rake spec</code></p>
182
+
183
+ <p>Run all the tests.</p>
184
+
185
+ <p><code>rake gem:build</code></p>
186
+
187
+ <p>Build a gem file.</p>
188
+
189
+ <p><code>rake gem:install</code></p>
190
+
191
+ <p>Install the gem you just built.</p>
192
+
193
+ <p><code>rake gem:uninstall</code></p>
194
+
195
+ <p>Uninstall r509-ca-http.</p>
196
+
197
+ <p><code>rake yard</code></p>
198
+
199
+ <p>Generate documentation.</p>
200
+ </div></div>
201
+
202
+ <div id="footer">
203
+ Generated on Thu Nov 8 14:58:26 2012 by
204
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
205
+ 0.8.3 (ruby-1.9.3).
206
+ </div>
207
+
208
+ </body>
209
+ </html>
@@ -0,0 +1,55 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html>
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+
7
+ <link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen" charset="utf-8" />
8
+
9
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
10
+
11
+
12
+
13
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
14
+
15
+ <script type="text/javascript" charset="utf-8" src="js/full_list.js"></script>
16
+
17
+
18
+ <base id="base_target" target="_parent" />
19
+ </head>
20
+ <body>
21
+ <script type="text/javascript" charset="utf-8">
22
+ if (window.top.frames.main) {
23
+ document.getElementById('base_target').target = 'main';
24
+ document.body.className = 'frames';
25
+ }
26
+ </script>
27
+ <div id="content">
28
+ <h1 id="full_list_header">File List</h1>
29
+ <div id="nav">
30
+
31
+ <span><a target="_self" href="class_list.html">
32
+ Classes
33
+ </a></span>
34
+
35
+ <span><a target="_self" href="method_list.html">
36
+ Methods
37
+ </a></span>
38
+
39
+ <span><a target="_self" href="file_list.html">
40
+ Files
41
+ </a></span>
42
+
43
+ </div>
44
+ <div id="search">Search: <input type="text" /></div>
45
+
46
+ <ul id="full_list" class="file">
47
+
48
+
49
+ <li class="r1"><a href="index.html" title="README">README</a></li>
50
+
51
+
52
+ </ul>
53
+ </div>
54
+ </body>
55
+ </html>
data/doc/frames.html ADDED
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
3
+
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
+ <head>
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
+ <title>Documentation by YARD 0.8.3</title>
8
+ </head>
9
+ <script type="text/javascript" charset="utf-8">
10
+ window.onload = function() {
11
+ var match = window.location.hash.match(/^#!(.+)/);
12
+ var name = 'index.html';
13
+ if (match) {
14
+ name = unescape(match[1]);
15
+ }
16
+ document.writeln('<frameset cols="20%,*">' +
17
+ '<frame name="list" src="class_list.html" />' +
18
+ '<frame name="main" src="' + name + '" />' +
19
+ '</frameset>');
20
+ }
21
+ </script>
22
+ <noscript>
23
+ <frameset cols="20%,*">
24
+ <frame name="list" src="class_list.html" />
25
+ <frame name="main" src="index.html" />
26
+ </frameset>
27
+ </noscript>
28
+ </html>
data/doc/index.html ADDED
@@ -0,0 +1,209 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII" />
6
+ <title>
7
+ File: README
8
+
9
+ &mdash; Documentation by YARD 0.8.3
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ hasFrames = window.top.frames.main ? true : false;
19
+ relpath = '';
20
+ framesUrl = "frames.html#!" + escape(window.location.href);
21
+ </script>
22
+
23
+
24
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
25
+
26
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
27
+
28
+
29
+ </head>
30
+ <body>
31
+ <div id="header">
32
+ <div id="menu">
33
+
34
+ <a href="_index.html">Index</a> &raquo;
35
+ <span class="title">File: README</span>
36
+
37
+
38
+ <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
39
+ </div>
40
+
41
+ <div id="search">
42
+
43
+ <a class="full_list_link" id="class_list_link"
44
+ href="class_list.html">
45
+ Class List
46
+ </a>
47
+
48
+ <a class="full_list_link" id="method_list_link"
49
+ href="method_list.html">
50
+ Method List
51
+ </a>
52
+
53
+ <a class="full_list_link" id="file_list_link"
54
+ href="file_list.html">
55
+ File List
56
+ </a>
57
+
58
+ </div>
59
+ <div class="clear"></div>
60
+ </div>
61
+
62
+ <iframe id="search_frame"></iframe>
63
+
64
+ <div id="content"><div id='filecontents'><h1>r509-ca-http</h1>
65
+
66
+ <p>r509-ca-http is an HTTP server that runs a certificate authority, for signing SSL certificates. It supports issuance and revocation, and is intended to be part of a complete certificate authority for use in production environments.</p>
67
+
68
+ <h2>Requirements/Installation</h2>
69
+
70
+ <p>You need r509 and sinatra. For development/tests you need rack-test and rspec.</p>
71
+
72
+ <h2>API</h2>
73
+
74
+ <h3>GET /1/crl/:ca/get</h3>
75
+
76
+ <p>Get the most recently generate CRL for the given <code>:ca</code>.</p>
77
+
78
+ <p>A new CRL is generated when a certificate is revoked or unrevoked, or if you explicitly generate it.</p>
79
+
80
+ <h3>GET /1/crl/:ca/generate</h3>
81
+
82
+ <p>Explicitly generate and get a new CRL for the given <code>:ca</code>.</p>
83
+
84
+ <h3>POST /1/certificate/issue</h3>
85
+
86
+ <p>Issue a certificate.</p>
87
+
88
+ <p>Required POST parameters:</p>
89
+
90
+ <ul>
91
+ <li>ca</li>
92
+ <li>profile</li>
93
+ <li>validityPeriod (in days)</li>
94
+ <li>csr (or spki)</li>
95
+ <li>subject</li>
96
+ </ul>
97
+
98
+ <p>The subject is provided like so:</p>
99
+
100
+ <pre class="code ruby"><code><span class='id identifier rubyid_subject'>subject</span><span class='lbracket'>[</span><span class='const'>CN</span><span class='rbracket'>]</span><span class='op'>=</span><span class='id identifier rubyid_domain'>domain</span><span class='period'>.</span><span class='id identifier rubyid_com'>com</span><span class='op'>&amp;</span><span class='id identifier rubyid_subject'>subject</span><span class='lbracket'>[</span><span class='const'>O</span><span class='rbracket'>]</span><span class='op'>=</span><span class='id identifier rubyid_orgname'>orgname</span><span class='op'>&amp;</span><span class='id identifier rubyid_subject'>subject</span><span class='lbracket'>[</span><span class='const'>L</span><span class='rbracket'>]</span><span class='op'>=</span><span class='id identifier rubyid_locality'>locality</span>
101
+ </code></pre>
102
+
103
+ <p>Optional POST parameters:</p>
104
+
105
+ <ul>
106
+ <li>extensions[subjectAlternativeName]</li>
107
+ </ul>
108
+
109
+ <p>SAN names are provided like so:</p>
110
+
111
+ <pre class="code ruby"><code><span class='id identifier rubyid_extensions'>extensions</span><span class='lbracket'>[</span><span class='id identifier rubyid_subjectAlternativeName'>subjectAlternativeName</span><span class='rbracket'>]</span><span class='lbracket'>[</span><span class='rbracket'>]</span><span class='op'>=</span><span class='id identifier rubyid_domain1'>domain1</span><span class='period'>.</span><span class='id identifier rubyid_com'>com</span><span class='op'>&amp;</span><span class='id identifier rubyid_extensions'>extensions</span><span class='lbracket'>[</span><span class='id identifier rubyid_subjectAlternativeName'>subjectAlternativeName</span><span class='rbracket'>]</span><span class='lbracket'>[</span><span class='rbracket'>]</span><span class='op'>=</span><span class='id identifier rubyid_domain2'>domain2</span><span class='period'>.</span><span class='id identifier rubyid_com'>com</span>
112
+ </code></pre>
113
+
114
+ <p>The issue method will return the PEM text of the issued certificate.</p>
115
+
116
+ <h3>POST /1/certificate/revoke</h3>
117
+
118
+ <p>Revoke a certificate.</p>
119
+
120
+ <p>Required POST parameters:</p>
121
+
122
+ <ul>
123
+ <li>ca</li>
124
+ <li>serial</li>
125
+ </ul>
126
+
127
+ <p>Optional POST parameters:</p>
128
+
129
+ <ul>
130
+ <li>reason (must be an integer, if it&#39;s not provided it defaults to 0)</li>
131
+ </ul>
132
+
133
+ <p>The revoke method returns the newly generated CRL, after revocation.</p>
134
+
135
+ <h3>POST /1/certificate/unrevoke</h3>
136
+
137
+ <p>Unrevoke a certificate. (IE, remove it from the CRL and return its OCSP status to valid.)</p>
138
+
139
+ <p>Required POST parameters:</p>
140
+
141
+ <ul>
142
+ <li>ca</li>
143
+ <li>serial</li>
144
+ </ul>
145
+
146
+ <p>The unrevoke method returns the newly generated CRL, after the certificate was removed from it.</p>
147
+
148
+ <h2>Helper pages</h2>
149
+
150
+ <p>These pages are present on the server, for you to work with the CA with a basic web interface. You should <em>not</em> expose these endpoints to anyone.</p>
151
+
152
+ <ul>
153
+ <li><p>/test/certificate/issue</p></li>
154
+ <li><p>/test/certificate/revoke</p></li>
155
+ <li><p>/test/certificate/unrevoke</p></li>
156
+ </ul>
157
+
158
+ <h2>certificate_authorities (config.yaml)</h2>
159
+
160
+ <p>You use the <code>config.yaml</code> file to specify information about your certificate authority. You can operate multiple certificate authorities, each of which can have multiple profiles, with one instance of r509-ca-http.</p>
161
+
162
+ <p>Information about how to construct the YAML can be found at <a href="https://github.com/reaperhulk/r509#config">the official r509 documentation</a>.</p>
163
+
164
+ <h2>Middleware (config.ru)</h2>
165
+
166
+ <p>Running r509-ca-http will let you issue and revoke certificates. But that&#39;s not everything you need to do, if you&#39;re going to run a CA. You&#39;re going to need information about validity, and you may want to save a record of issued certificates to the filesystem.</p>
167
+
168
+ <p>For that, we&#39;ve created a few pieces of Rack middleware for your use.</p>
169
+
170
+ <ul>
171
+ <li><a href="https://github.com/sirsean/r509-middleware-validity">r509-middleware-validity</a></li>
172
+ <li><a href="https://github.com/sirsean/r509-middleware-certwriter">r509-middleware-certwriter</a></li>
173
+ </ul>
174
+
175
+ <p>After installing one or both of them, you&#39;ll have to edit your <code>config.ru`` and/or</code>config.yaml``` files.</p>
176
+
177
+ <h2>Rake tasks</h2>
178
+
179
+ <p>There are a few things you can do with Rake.</p>
180
+
181
+ <p><code>rake spec</code></p>
182
+
183
+ <p>Run all the tests.</p>
184
+
185
+ <p><code>rake gem:build</code></p>
186
+
187
+ <p>Build a gem file.</p>
188
+
189
+ <p><code>rake gem:install</code></p>
190
+
191
+ <p>Install the gem you just built.</p>
192
+
193
+ <p><code>rake gem:uninstall</code></p>
194
+
195
+ <p>Uninstall r509-ca-http.</p>
196
+
197
+ <p><code>rake yard</code></p>
198
+
199
+ <p>Generate documentation.</p>
200
+ </div></div>
201
+
202
+ <div id="footer">
203
+ Generated on Thu Nov 8 14:58:26 2012 by
204
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
205
+ 0.8.3 (ruby-1.9.3).
206
+ </div>
207
+
208
+ </body>
209
+ </html>