Topic: SSL Solution For Michael Hartl's RoR Tutorial Chapter 9 Exercise 3
This is my attempt at solving Chapter 9 Exercise 3 of Michael Hartl's Ruby on Rails Tutorial. I'm going to make a couple trips around the mulberry bush so please be patient with me.
CONFIGURATION
I'm running Ubuntu Linux version 10.10 with Rails 3.0.9 and Ruby 1.9.2p180. For more information on this configuration see:
http://railsforum.com/viewtopic.php?pid=140122#p140122
FIXING THE ROUTES TABLE AND RSPEC TESTS
Step 1) In routes.rb
change this:
resources :sessions, :only => [:new, :create, :destroy]
to this:
resources :sessions, :only => [:new, :create, :destroy],
:defaults => {:protocol => "https"}
Step 2) Restart Spork and Autotest. Notice that Autotest now logs several failures telling you that there is no route to controller "sessions" with action "create".
Step 3) In sessions_controller_spec.rb
Change this:
post :create, :session => @attr
to this:
post :create, :session => @attr, :protocol => 'https'
I had to make this change in five places.
This will fix the Autotest failures.
Step 4) Restart Spork and Autotest. All tests should pass giving a green smiley face.
Now as it turns out, all of the above was an exercise in futility. We'll see why later. Just remember that I said we'd make a couple passes around the mulberry bush. At this point you should change everything back like it was.
------------------------------------------------------------------------------
CONFIGURING WEBRICK FOR SSL/TLS
Attribution: This part of the solution came from a post by Chris Rohr at:
http://www.nearinfinity.com/blogs/chris
e_ssl.html
Step 1) Make a backup copy of /script/rails.
Step 2) Replace the contents of /script/rails with:
#!/usr/bin/env ruby1.8
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
require 'rubygems'
require 'rails/commands/server'
require 'rack'
require 'webrick'
require 'webrick/https'
module Rails
class Server < ::Rack::Server
def default_options
super.merge({
:Port => 3001,
:environment => (ENV['RAILS_ENV'] || "development").dup,
:daemonize => false,
:debugger => false,
:pid => File.expand_path("tmp/pids/server.pid"),
:config => File.expand_path("config.ru"),
:SSLEnable => true,
:SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
:SSLPrivateKey => OpenSSL::PKey::RSA.new(
File.open("/home/name4/ssl/ca.key").read), # Fix this path!
:SSLCertificate => OpenSSL::X509::Certificate.new(
File.open("/home/name4/ssl/ca.crt").read), # Fix this path!
:SSLCertName => [["CN", WEBrick::Utils::getservername]]
})
end
end
end
APP_PATH = File.expand_path('../../config/application', __FILE__)
require File.expand_path('../../config/boot', __FILE__)
require 'rails/commands'
Step 3) Please note the two lines above that contain "# Fix this path!" You can't fix them yet, but don't forget to fix them later after you create ca.key and ca.crt.
------------------------------------------------------------------------------
MAKING YOUR VERY OWN SSL CERTIFICATE
I know, the tutorial says you don't need to make an SSL certificate just for development. I'm sure that's true, but I couldn't figure out how to make it work without one. In any case, I thought, "How hard can it be to make my own certificate, and I need to learn how to make one anyway because one day I'll need to deploy a 'real' application."
Attribution: This part of the solution came from a post by Paul Bramscher at:
http://www.tc.umn.edu/~brams006/selfsign.html
Configuration: You need to have the openssl gems installed. That is, you need the following lines in your Gemfile:
gem 'openssl-extensions', '1.1.0'
gem 'openssl-nonblock', '0.2.1'
If necessary, add these lines to the first group of gems at the top of your Gemfile, and then from a command prompt run:
$ bundle install
You can find more extensive configuration help at:
http://railsforum.com/viewtopic.php?pid=140122#p140122
and in section 1.2.4 of the tutorial.
Now here we go.
Step 1) From a shell prompt change directory to your home directory.
$ cd ~
Step 2) Make a directory to hold your SSL certificate.
$ mkdir ssl
Step 3) Navigate to the newly created directory.
$ cd ssl
Step 4) Create your CA key.
$ openssl genrsa -des3 -out ca.key 4096
Step 5) Generate your certificate.
Note: This command actually makes you a certificate authority (although not a trusted one) so you can use it to run a server and/or sign other SSL certificates.
openssl req -new -x509 -days 7300 -key ca.key -out ca.crt
You will now be asked to enter a pass phrase. Since this certificate is just for local testing enter something short and simple like "passphrase". Then press Enter. Note: The pass phrase will not display on the terminal, and the cursor will not move. Don't let this bother you. Just type the passphrase and press Enter.
Be sure to write the pass phrase on a yellow sticky note, and post it somewhere where everyone can see it. ![]()
If you prefer a more secure pass phrase, you can get a truly random character string from:
https://www.grc.com/passwords.htm
Step 6)
After you enter the pass phrase you will be asked a series of questions. Here are the questions and some possible answers:
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Texas
Locality Name (eg, city) []:Dallas
Organization Name (eg, company) [Internet Widgits Pty Ltd]:None Whatsoever
Organizational Unit Name (eg, section) []:Software Development
Common Name (eg, YOUR name) []:localhost
Email Address []:localhost@mycomputer.com
Step 7)
Your certificate is now ready to use, but there's still one tiny step to complete. Open /script/rails with your favorite text editor, and fix the paths in the two lines that contain "# Fix this path!"
-------------------------------------------------------------------------
TESTING YOUR NEW CERTIFICATE
Step 1) Shut down Webrick if it's already running.
Step 2) From a command prompt start Webrick.
$ rails server
Webrick will prompt you to:
Enter PEM pass phrase:
Type the pass phrase you wrote on the yellow sticky note then press Enter. As before the pass phrase will not display.
Step 3) Start your favorite browser and enter the following URL:
https://localhost:3001/
At this point your browser will probably complain bitterly that the certificate is not trusted. Don't let that browser push you around. Tell it to trust the certificate anyway!
Step 4)
Your Sample App should appear, and it should be fully operational. But there's still one tiny problem.
-------------------------------------------------------------------------
WHY DO ALL THE PAGES DISPLAY IN SECURE MODE?
Well, remember the mulberry bush? If I were the creator of the universe, which, alas, I am not, we would simply re-edit routes.rb replacing this:
resources :sessions, :only => [:new, :create, :destroy]
with this:
resources :sessions, :only => [:new, :create, :destroy],
:defaults => {:protocol => "https"}
Unfortunately, this maneuver doesn't accomplish a thing (except to break the rspec tests).
You can run two instances of the Webrick server. I've run an HTTP version on port 3000 along with an HTTPS version on port 3001. Unfortunately, this doesn't fix anything either. Whichever Webrick server you launch Sample App on is the server you will keep using. Apparently at least one developer has gotten this to work. Check out Alan's comment at the end of the post at:
http://www.nearinfinity.com/blogs/chris e_ssl.html
This situation isn't necessarily all bad. Check out the post at:
https://www.eff.org/pages/how-deploy-https-correctly
In this post the Electronic Frontier Foundation makes the point that requiring HTTPS for passwords only is a twentieth century concept. Now days most web pages have content coming from a multitude of third party sources (i.e. ad servers). This third party content can attempt to steal your session cookie, which is almost as effective as stealing your user id and password.
All security issues aside, I'd still like to know how to get Rails/Webrick to route some pages to HTTP and others to HTTPS. If anyone out there on the Rails knows how to do it, I'd love to read your comment.
Doug Witmer
Last edited by DougW4 (2011-07-25 20:47:09)