Rails Two-factor Authentication

Given the problems passwords pose, isn't it time to offer people a second authentication factor? Your bank does it. Google does it. Even games do it. You can too. How hard is it to get Rails set up with a one-button six digit authenticator? Not hard at all! The hardest part was knowing where to look and what to get.

Close inspection of the dongles we already have revealed one name printed on them all: VASCO. VASCO provides the physical token you hold in your hand. We ordered a few of these. VASCO also provides the server software to authenticate tokens. The software comes in all sizes: enterprise, cloud, but for us the perfect match is just a C API called the VACMAN Controller. It runs on Windows, Linux, some more exotic OSes, but not Mac OS X.

How does it work? Each token has a serial number and contains a clock. When you press the button, the token shows a six digit one-time password based off that clock. Send the serial number, the password, and a little magic to the C API. It returns whether everything matches up right now. (So the clock on your server better be on time.)

How does the C API know whether the serial number and password match? In the beginning, VASCO creates a special encrypted file for you. It records how the clock and the serial number are synchronized. Before anyone can use their tokens, you have the API import the special file. It returns a data-structure with authentication information. Pass this magic struct with the serial number and password when authenticating. After authenticating, the data-structure is updated. Besides simple statistics like number of successful authentication attempts, the data structure stores information about token's internal clock. This allows the API to compensate for gradual time drift. The API itself is stateless. It's your job to keep track of the tokens and the data-structure.

Okay, but how does it work with Rails? As always, apply a little bit of glue. SWIG makes wrapping C APIs easy. This time was no exception though we did need to do a little more to allocate and free data-structures than usual. For the database, use ActiveRecord if that's your thing. We went with Sequal. We used two tables:

  • One table maps user names to token ids.
  • The other table maps token ids to magic data-structure blobs.

That's it really. We just use a script to import the import the token info. We don't use enough tokens to try to automate further.

Posted by william 15 Nov 2012 at 02:07AM


Releasing Textilize gem for Rails3 without C extensions

      Rails 3.X doesn't have the textilize and textilize_without_paragraph helper methods. Textilize is a gem brings back the missing method for Rails 3, and it includes the library RedCloth 3.0.4, which doesn't need to be compiled on server. Btw, The newest RedCloth is currently at 4.X though, it requires compiling C extension.

  

      The reason we need this gem is that we use :textilize at a few places in our apps, and we don't need super fast RedCloth, we just need a working version that don't force us to install C extensions on various production servers. This could be useful for bundle-package usage, where you can rely on the bundle/cache gems.

  
Related Links: 

       Sourcecode: http://github.com/kudelabs/textilize 
       RubyGem: http://rubygems.org/gems/textilize

  

Posted by Mysen 06 Jul 2012 at 04:51AM


tags in git for sane version numbers

The problem

In the svn days, branching was expensive, repositories were centralized ... life was hard. But one thing was easy; each revision had a number and that number went up each time a change was committed to the repository. This made versioning easy: v1, then v2, later v345, finally v1202, anyone can see this and understand.

When switching to git, there is a bit of a learning curve, as each commit is named with an unpronounceable 40 character hexidecimal hash. It's really easy to tell a client, "I just deployed v434, it has all the features we talked about yesterday" Or, "Yeah, you're looking at v57, the new features are in v62" . Its much more difficult to tell a client, "Sorry for the mixup, you are looking at gdac40b3 but the bug is fixed in 616f65bb". I can already see eyes glazing over in confusion.

git has a really handy tags feature. It is perfect for large complicated projects where several commits go into each new release, and the release schedule is on the scale of weeks rather than days. You tag 1.0, then 1.1, 1.1.1 - and so on. These are sane version numbers and are easy to talk about. The problem is that they take work. When you are working on something uncomplicated and the release cycle measures in days or hours, nothing beats the old commit by commit versioning system.

The solution

To get automatic revision numbers in git, we use the native tags, but in a slightly different way. The git describe, command has a handy feature, it can figure out how many commits your repository has after the last tag. What this means is that when you create a tag, say 1.0, 4 commits later git describe will call this "1.0-4-616f65bb". What I propose is to use this feature to our advantage. Rather than tag at the end of a target version, say 1.1.1, we tag at the beginning, and let git to the work. And rather than 1.1.1, we use a meaningful name. So for example, I might use a tag like this:

$ git tag -a 'milestone1' -m 'starting work for milestone 1, due in 2 weeks'
$ git push --tags

From here on out, git will automatically count the commits for us, so we have a sane version number to talk about with clients. If we want to see it, all we need to do is this:

$ git describe
milestone1-34-g4a1e1d4

Which I can then use to tell the client, "Ok, I just deployed milestone1-34, we added the feature to read your thoughts, please check it out and let me know - oh wait ... the software can tell me."

Something that we always do is embed the current revision somewhere into the software so that we know what version the user is seeing. In Rails, I just added this to config/initializers/git_helper.rb

# VERSIONING
git_version_cmd = "git describe"
$revision = `#{git_version_cmd}`
$revision = $revision.strip
puts "starting version: #{$revision}"

I can now put $revision in the footer, or hide it in a comment somewhere on the page. This helps keep everyone in the loop and prevent misunderstandings about what version someone may be looking at.

This is just one way to manage versions in git, we'd love to hear yours!

Posted by adevadeh 22 Dec 2011 at 07:50AM


conflict-when-git-up

When I started to use Git, I felt really pain for it. The problem is that when your team mate told you that he has checked in, and you are willing to see the update right away. So you just 'git up', and then you probably see something like 'you need to commit first before merging'. Oops, but I am just in the middle of modifying something, I am not ready at all to check in.

Well, that's what git up are different from svn up. Here, one tips is:

git stash save   # this will save your local changes to a temporary place, and clean up your workspace
git up                 # here, you could just update to the HEAD of your branch, probably master
git stash pop    # then you could get your local change back, and you probably need to fix the conflicts here

http://lists-archives.org/git/708097-you-have-local-changes-cannot-switch-branches-error-question.html

Posted by Shaokun 22 Dec 2011 at 07:49AM


Some Fun with Ruby Abstract Syntax Tree

For a while, I've been interested in gems that provide access to Abstract Syntax Tree (AST) representation of Ruby code, and potential possibilities they open. Just a couple days ago this interest was triggered again. The question that arose at the moment was:

  • say, we're facing somebody else's lengthy, sophisticated and rather unfamiliar code which we're planning to reuse. How do we find out where the code may be cache'ing results in instance variables - therefore, possibly, causing unplanned and undesired side effects?

Perhaps, we could convert the given piece of Ruby code into AST and then list all lines that correspond to instance variable assignment nodes... This felt like an interesting exercise so I ended up writing a little code snippet for that.

A few other possible AST uses, I thought, could be:

  • listing all methods defined in a specific file;
  • listing all method calls in a given class or method (e.g. to figure out external dependencies for refactoring or unit-testing purposes);
  • listing class variable assignments.

So, the initial script evolved into a more generic parsetree_locator.rb utility (note: requires 'ruby-parser' gem; also, only tried it on MRI Ruby 1.9).

Let me present a few examples of how the utility works.

 

Examples

Say, we have the following Ruby code in 'example.rb' file:

module M
  class C
    def meth
      @a = 2
      b = 3
    end

    def call_meth
      meth
    end

    def another_meth
      @n = 95
      call_meth
    end
  end
end

1) List all instance variable assignments - "iasgn" AST nodes:

$ ruby parsetree_locator.rb "iasgn" "example.rb"

Result:

Line nr | Module, class, method                              | Code
4:      | module M, class C#meth                             | @a = 2
13:     | module M, class C#another_meth                     | @n = 95

2) List all defined instance methods - "defn" AST nodes:

$ ruby parsetree_locator.rb "defn" example.rb

Result:

Line nr | Module, class, method                              | Code
3:      | module M, class C                                  | def meth
8:      | module M, class C                                  | def call_meth
12:     | module M, class C                                  | def another_meth

3) List all method calls - "call" nodes:

$ ruby parsetree_locator.rb "call" example.rb

Result:

Line nr | Module, class, method                              | Code
10:     | module M, class C#call_meth                        | end
15:     | module M, class C#another_meth                     | end

-- seems like the line numbers are slightly off in this case. The author of 'ruby_parser' gem mentions that it may happen; the results seem reasonable most of the time, though.

Hope that somebody else finds this utility useful as well, enjoy! parsetree_locator on GitHub

Posted by Jevgenij Solovjov 24 Oct 2011 at 07:52AM


Rails on Campus Wrap-up

After 2 great sessions of Rails on Campus: 华工版, we'd like to thank everyone who took part in helping to plan and organize this event. We learned a lot from the experience, and we hope the attendees did as well. We plan to take our materials from this first run, refactor, and put on a better program next year!

Before we close out for the year though, I wanted to go over what you can do to continue learning on your own.

Install Rails

http://railsinstaller.org - Download and run the installer. It will install everything you need to get started writing your own Rails apps (ruby, git, rubygems, rails).

Get the demo code

http://github.com/kudelabs/roc-demo2 - Clone the project and get it running on your computer .

git clone git://github.com/kudelabs/roc-demo2.git 
cd roc-demo2
rake db:migrate
rails s
open http://localhost:3000

Write some code

http://notepad-plus-plus.org/ - You can use any text editor to write code, but its much easier in a real code editor like Notepad++. It's free, give it a try.
http://http://guides.rubyonrails.org/getting_started.html - Take a look at the Rails Guides for more in-depth tutorials
http://asciicasts.com - Another great resource with tons of tips and information

Share with the world

http://heroku.com - A free service to host your amazing Rails app! It works right from the command line and in 5 minutes you have a public site that you can show to anyone.

Just Do It

So now you have no excuse. You have the tools, you have the code, you have the servers. Go write an inspiring app and make us proud!

Posted by adevadeh 09 Jun 2011 at 09:24AM


installing rvm on older systems (RHEL4)

I recently had trouble installing the excellent Ruby Version Manager (rvm) onto an older production server. While bash scripting isn't my strong suite, i managed to track down the issue to this line in scripts/manage.sh:
__rvm_run "extract" "bunzip2 < '${rvm_archives_path}/$rvm_ruby_package_file.$rvm_archive_extension' | tar xf - -C ${rvm_tmp_path:-/tmp}/rvm_src_$$" "$rvm_ruby_string - #extracting $rvm_ruby_package_file to ${rvm_src_path}/$rvm_ruby_string"
Turned out that for whatever reason, this line simply didn't work in RHEL4. Luckily, it didn't take much to fix it. The first thing I did was split it into 2 lines, so I could better see where it was failing. Turns out, performing this action in 2 lines was all that needed to happen, and this worked fine.
__rvm_run "extract" "bunzip2 '${rvm_archives_path}/$rvm_ruby_package_file.$rvm_archive_extension'"
__rvm_run "extract" "tar xf ${rvm_archives_path}/$rvm_ruby_package_file.tar -C ${rvm_tmp_path:-/tmp}/rvm_src_$$" "$rvm_ruby_string - #extracting $rvm_ruby_package_file to ${rvm_src_path}/$rvm_ruby_string"
So, if rvm is failing to install ruby1.9.2 on older linux distros, this may help. I've already created a github pull request, hopefully this will get rolled into a later version of rvm. Many thanks to Wayne for this amazing package!

Posted by adevadeh 19 May 2011 at 08:09AM


three steps to upgrade redmine from 0.9.x stable to 1.1 stable

Redmine makes it pretty easy and smooth for us to upgrade itself. Here is a link for general upgrade from Redmine: RedmineUpgrade.

In 1.1 stable version, there are some good new features that 0.9.3 doesn't have, i,e: the Gantt chart , the Calendar, and the new concept of Subtasks/Parent tasks and so on. For more detailed features of newest redmine, you may visit: Features.

If you have redmine running at an old version like 0.9.x, and feel strongly like upgrading redmine to the latest stable version, you may try this simplest solution:

Step 1: Backup files/ and database, very important!
Step 2: svn switch http://redmine.rubyforge.org/svn/branches/1.1-stable 
Step 3: rake db:migrate RAILS_ENV=production

Note that Steps 2 and 3 must be done in your existing redmine root.

After you have completed the above three steps, just restart your application and you will see the new exciting Redmine, hooray!

Just in case of you are not familiar with linux, let me explain more:
1. How to backup files?

cp -r your_redmine_root/files your_backup_destination/files 
2. How to backup database?
mysqldump -u username -p password redmine_db_name >  your_backup_destination/redmine_db_backup.sql

Posted by Mysen 09 Feb 2011 at 09:15AM


Setting up rubygems without root access

Recently we had to install our rails app on a box, but we didn't have root access. The machine had ruby 1.8.6 and rubygems 0.9.6 (ouch). We can live with Ruby 1.8.6; but to run modern rails, we needed modern rubygems.

The rubygems install page has a helpful section on how to install locally without root access. Note: be sure to add export GEM_HOME=~/rubygems/gems to your .bashrc or your .bash_profile or else the next time you log in, your system gets confused again.

$ mkdir rubygems
$ cd rubygems-a.b.c
$ export GEM_HOME=~/rubygems/gems
$ ruby setup.rb --prefix=~/rubygems

Unfortunately, this didn't go as smoothly as I hoped. The result:

" `gem_original_require': no such file to load -- rubygems/exceptions"

and many other similar error messages.

The issue was that since the server installation already had an old version of rubygems installed, my local gem script was calling up the old rubygems files, but using my new GEM_HOME. A big mess.

What needs to happen is that your new gem executable needs to load your new rubygems files, and work with your new GEM_HOME. There may be a better way to do this, but I have found a workable solution for my case. It involves messing with the executable files that rubygems installs.

If you take a look at your gem executable, you'll see it is just a text file, a ruby program that executes itself.

$ cat  ~/rubygems/bin/gem

#!/usr/local/bin/ruby
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++

require 'rubygems'
require 'rubygems/gem_runner'
require 'rubygems/exceptions'

...

If you are familiar with shell scripts, you'll know that the first line (the shebang) specifies the binary to use to process the file. In this case, its #!/usr/local/bin/ruby. In general this is great. Ruby loads up the file and runs the script and magic happens. But what if the require 'rubygems' line is loading up the wrong rubygems?

We need to tell ruby where to find our custom rubygems libraries. Luckily, ruby has an option for this, -I path/to/lib. So, all we need to do is open up our gem executable and modify the shebang line to include this option.

$ vim  ~/rubygems/bin/gem

#!/usr/local/bin/ruby -I ~/rubygems/lib
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++

require 'rubygems'
require 'rubygems/gem_runner'
require 'rubygems/exceptions'

This tells the ruby interpreter to start the process with our custom path in the include path. If we have a newer version of the rubygems library there, they get required instead of the old versions. I can now install gems locally into my GEM_HOME without needing root access like so:

$ gem install mongrel

But that's not all. mongrel also installs its own executable, and when you try to run it, it will require rubygems. And yes, you guessed it, it will find the old version of rubygems and get completely confused. So again, we need to go into the executable file ~/rubygems/gems/bin/mongrel_rails and modify the shebang line.

As far as I can tell, you would need to do this for each and every gem that installs its own executable.

Update: after further consideration, using the $LOAD_PATH environment variable would probably be more robust, but my app is already installed. Perhaps you will let me know how it goes with $LOAD_PATH

Posted by adevadeh 20 Jul 2010 at 03:52AM


Start a new project and push to remote git repo

Like many folks out there, we have been making the switch to git from svn. Although we struggled with git early on, after using both for some time I have come to appreciate the benefits of git. So here is our way of starting new projects with git.

Using gitosis on our server, we create an empty remote repo first. Then, one guy gets the project going and pushes the code into the empty repo. Here are the commands to get that going.

$ cd path/to/new/project
$ git init
$ git add .
$ git commit -m 'initial commit'
$ git remote add origin git@devserver.com:newproject.git
$ git push origin master

Posted by adevadeh 25 May 2010 at 08:09AM



>