namespace :sshkey do class PublicKeyPathNotFound < StandardError end task(:default) { list } desc <<-DESC List all registered SSH keys. DESC task :list do puts_title "Registered SSH keys" puts_list SshKey.all, :table => true do |t| t.col("Public key") { |k| k.public_key.to_s[0, 50] + '...' } end end registration_env_vars = <<-DESC Environment variables: (optional) $FILE: path/to/id_{rsa,dsa}.pub Default: your public key is searched for at the usual locations. (optional) STDIN: the public key can be fed through STDIN instead of by path. Example: $ #{command "sshkey:register"} < path/to/the/key.pub DESC desc <<-DESC Register your public SSH key. You can register more than one. Doing so grants you password-less SSH/SFTP/SCP access to all UNIX accounts created either automatically or manually via #{qcommand "vps:user:add"}. Upon registration, the new key will be granted access all UNIX accounts of all your VPS's (actually, only the ones that have a home folder). It will also automatically be granted access to UNIX accounts created later. #{registration_env_vars} DESC task :register do current_key = local_key! puts_title "Registering SSH key" puts "Public key at: #{current_key}" key = SshKey.new :public_key => current_key.read try_save key do puts_title "SSH key registered" puts(key.public_key) end end desc <<-DESC Make sure that your public key is registered; register it otherwise. If you don't have a pair of keys (private and public) yet, one is attempted to be generated for you at ~/.ssh. If even the generation failed, all UNIX accounts are switched to password mode. In this mode, each time an account is created, a password is generated for you to log in with. At creation time, an e-mail is sent to you containing SSH connection details, including the generated password. #{registration_env_vars} DESC task :ensure_registered do begin current_key = local_key rescue PublicKeyPathNotFound if system("which ssh-keygen") sh %{echo | ssh-keygen -t dsa -P ''} register else Account.put(:password_auth) error! <<-MSG You do not appear to already have an SSH key pair present at the regular location. One has been attempted to be generated for you but the #{q "ssh-keygen"} was missing. As a consequence, password-authentication have been enabled so that you can connect to each account on your VPS's using passwords instead of a public key. Also, whenever the #{q "ssh"} is supposed to be executed, you will be presented with connections details for use in a graphical client application such as PuTTy and WinSCP (for Windows). MSG end else puts_title "Status of your public key" begin SshKey.create :public_key => current_key.read rescue WebService::ResourceInvalid puts "The public key of the current user (#{ENV['USER']}) is registered." else puts "The public key of the current user (#{ENV['USER']}) has been registered successfully." end end end desc <<-DESC Unregister a key. It will be revoked access from all UNIX accounts it is currently granted access to, and won't be automatically granted access to the UNIX account of new website backends anymore. Environment variables: $ID: the ID of the key to unregister (get the list with #{qcommand "sshkey:list"}). DESC task :unregister do id = require_id! SshKey.delete(id) puts_title "Request sent" puts "SSH key successfully scheduled for unregistration." end def require_id! ENV["ID"] or error! <<-MSG The ID of the key to deal with must be specified by setting the ID environment variable. To list all registered SSH keys, run #{qcommand "sshkey:list"}. MSG end def local_key! local_key rescue PublicKeyPathNotFound error! $!.message end def local_key if !$stdin.tty? file = STDINWrapper.new elsif path = ENV["FILE"] file = Pathname(path) raise PublicKeyPathNotFound, "No such file: #{path}." unless file.file? else file = Pathname.glob("{.,#{ENV['HOME']}/.{ssh,ssh2}}/id_{dsa,rsa}.pub{,.txt}").first end file or raise PublicKeyPathNotFound, "Could not guess the path of your public SSH key." end class STDINWrapper def to_s "STDIN" end def read $stdin.gets end end end