Monday, December 27, 2010

Securing the Redmine_S3 plugin

We run redmine internally here at Fuery Solutions. Redmine is a fantastic tool for managing software development projects.

One of the unfortunate "features" redmine has is the habit of storing uploaded files without any security, regardless of whether the system itself is password protected or not. The redmine s3 plugin echoes this habit, setting all uploaded documents to readable by the entire internet. Obviously, the URLs are somewhat obscure, but as the cliche goes, obscurity is not security.

Here are instructions for altering the plugin to use temporary authorized URLs. This effectively offloads the security requirements to Amazon's formidable infrastructure.

These instructions apply to:

  • Redmine 1.0.x
  • Redmine_S3 v 0.03
Files you'll be editing (where "redmine" is your rails application root):
  1. redmine/vendor/plugins/redmine_s3/lib/redmine_s3/attachment_patch.rb
  2. redmine/vendor/plugins/redmine_s3/lib/redmine_s3/attachments_controller_patch.rb
  3. redmine/vendor/plugins/redmine_s3/lib/redmine_s3/connection.rb
First, we need to disable the "set newly uploaded files to be readable" command. This entails commenting a single line in attachment_patch.rb, on line 24:

#Private (not readable by everyone) is the default.
#RedmineS3::Connection.publicly_readable!(path_to_file)

This handles newly created files. Next, we need to add the capability to retrieve a URI with the AWS temporary authorization keys. The S3 lib the plugin uses actually contains theses goodies already, so we just need a wrapper function in connection.rb that uses the QueryStringAuthGenerator class. This function isn't as clean as it could be, but we threw this together in an hour. Add this function to the Connection class in connection.rb:


def self.private_uri(filepath)
 load_options unless @@access_key_id && @@secret_acces_key
 @@qs_conn = S3::QueryStringAuthGenerator.new(@@access_key_id, @@secret_acces_key, false) unless @@qs_conn
 @@qs_conn.get(bucket, filepath)
end


I added this on line 37, between the bucket and uri functions. You'll also, of course, need to initialize @@qs_conn by adding this at the beginning of the file (line 7 or so):


@@qs_conn = nil

Finally, we need to adjust the controller function that handles the response to the attachment GET requests themselves. Adjust attachments_controller_path.rb on line 23:

#Comment the current line 23.
#redirect_to("#{RedmineS3::Connection.uri/#{@attachment.path_to_file}") 
#New code
redirect_to("#{RedmineS3::Connection.private_uri(@attachment.path_to_file)}") 


Don't forget to restart your application after performing these changes. You'll also, of course, need to adjust the file settings in AWS for previously uploaded files. Although this new code works for viewing those files, the security settings ("visible to everyone") need to be reset manually.


Tuesday, November 2, 2010

At a Glance To-do List for Running Rails 2 and Rails 3 on the Same Linux Server

This is geeky. You've been warned.

Environment: Rails 2.3.5 app - redmine,our internal project management tool, in our case - running on Ubuntu 10.04.
Requirement: Install a Rails 3 app - our new corp web site in this case. Goodbye, Wordpress, hello home-grown RoR happiness.

Note: this will down your rails 2.3.5 app briefly.

  1. Make sure your core libs are up to date:
    1.  apt-get install libyaml-ruby
    2.  apt-get install libzlib-ruby
  2. Update rubygems. Ubuntu won't let you using "gem install rubygems", so do this instead:
    1. gem install rubygems-update
    2. rubygems-update
  3. Install bundler
    1. gem install bundler
  4. Install Rails 3. This will take a few minutes.
    1. gem install rails
  5. Go to your Rails 3 app directory and run:
    1. bundle install
  6. Reload apache (optional)
    1. /etc/init.d/apache2 reload OR service apache2 reload
  7. Your old Rails 2 app will now be down and your new Rails 3 app is running. Now we reinstall Rails 2. Bundler lets these coexist peacefully:
    1. gem install rails -v=2.3.5
  8. Reload apache. 
    1. /etc/init.d/apache2 reload OR service apache2 reload
Check your work by accessing both of your applications. Voila!