Switching users during a capistrano deploy

We have a complicated deployment on my current project which includes
running several commands as a different user from the main deployment
user. Normally, this wouldn’t be a problem since the sudo method
provides an option called ‘as’:

task :run_command_as_another_user do
  sudo "whoami", :as => "another_user"
end

Unfortunately, we do not have sudo access to our servers. Instead of
using sudo, we wrote a new method called with_user which will execute a
block as a different user:

task :try_another_user do
  with_user("another_user", "another_password") do
    run "whoami"
  end
end

The with_user method will set the user and password back to the
original values once the block is complete. For example:

task :whoami do
  set :user, 'original'
  set :password, 'original'

  run 'whoami'
  with_user("someone_else", 'password') do
    run "whoami"
  end
  run 'whoami'
end

The output of the previous task (stripped down) is:

 ** [out :: 127.0.0.1] original
 ** [out :: 127.0.0.1] someone_else
 ** [out :: 127.0.0.1] original

The implementation of with_user is:

def with_user(new_user, new_pass, &block)
  old_user, old_pass = user, password
  set :user, new_user
  set :password, new_pass
  close_sessions
  yield
  set :user, old_user
  set :password, old_pass
  close_sessions
end

def close_sessions
  sessions.values.each { |session| session.close }
  sessions.clear
end

It saves the old user and password and then sets the new values. Then,
it disconnects from all of the servers, which forces a reconnect on the
next command with the new user and password. When the block is complete,
it resets the user and password and disconnects again.

The repeated reconnecting is not the most efficient solution, but it is
simple and works for us.

Paul Gross

Paul Gross

I'm a lead software developer in Seattle working for Braintree Payments.

Read More