Disable dangerous rake tasks in production


Yesterday, we had to restore the production DB from a backup, since we ran "rake db:schema:load" in production by mistake. To avoid that problem in the future, I decided to disable that task, and others than can screw with the DB, in production. 

It was a matter of adding a prerequisite to those dangerous tasks, that checks if they are being run in production, and exit accordingly. I also added a flag to override this safeguard, together with some code to backup the DB. To do this, I added the following code to lib/tasks/disable_db_tasks_on_production.rake:


DISABLED_TASKS = [
  'db:drop',
  'db:migrate:reset',
  'db:schema:load',
  'db:seed',
  # ...
]

namespace :db do
  desc "Disable a task in production environment"
  task :guard_for_production do
    if Rails.env.production?
      if ENV['I_KNOW_THIS_MAY_SCREW_THE_DB'] != "1"
        puts 'This task is disabled in production.'
        puts 'If you really want to run it, call it again with `I_KNOW_THIS_MAY_SCREW_THE_DB=1`'
        exit
      else
        require 'heroku'
        puts 'Making a backup of the database, just in case...'
        puts `heroku pgbackups:capture`
      end
    end
  end
end

DISABLED_TASKS.each do |task|
  Rake::Task[task].enhance ['db:guard_for_production']
end
It would be nice to add something like this to the default Rails app, since, if you are reading this, chances are high that is too late for this to protect you by now :)

Some feedback from reddit's darkphnx, nice to know we're not the only ones :)
Initially you think "What sort of moron would write db:schema:load" on a production machine, but it's not that simple. 
Plenty of application hosting systems will look at what sort of application you're deploying and make assumptions about what commands should be run on first deployment. Very often one of these is "rake db:schema:load".Let's say you're deploying to a new hosting environment, but pointing to an existing database. If you forget to check what commands are going to run on first deployment deployment it will come along and be very helpful "oh, this is the first time you've deployed this app, I'll load the database schema for you". db:schema:load drops any existing tables.If you're not watching the deployment carefully, the first time you'll know is when the deployment is complete all your data is gone. If you're lucky you were watching and you've only lost a couple of tables.Source: Did exactly this, had to restore a 50GB table from backup.

No comments:

Post a Comment