def install_packages(): """ Install a set of baseline packages and configure where necessary """ if env.verbosity: print env.host, "INSTALLING & CONFIGURING NODE PACKAGES:" #Get a list of installed packages p = run("dpkg -l | awk '/ii/ {print $2}'").split('\n') #Remove apparmor - TODO we may enable this later if env.overwrite or not server_state('apparmor-disabled') and 'apparmor' in p: with settings(warn_only=True): sudo('/etc/init.d/apparmor stop') sudo('update-rc.d -f apparmor remove') set_server_state('apparmor-disabled') #The principle we will use is to only install configurations and packages #if they do not already exist (ie not manually installed or other method) env.installed_packages[env.host] = [] role = env.role_lookup[env.host_string] packages = get_packages() for package in packages: if not package in p: install_package(package) if env.verbosity: print ' * installed',package env.installed_packages[env.host].append(package) if env.overwrite or env.installed_packages[env.host]: #always store the latest complete list set_server_state('packages_installed', packages) env.installed_packages[env.host] = packages if env.overwrite and 'apache2' in env.installed_packages[env.host]: #some sensible defaults -might move to putting this config in a template sudo("rm -f /etc/apache2/sites-enabled/000-default") sed('/etc/apache2/apache2.conf',before='KeepAlive On',after='KeepAlive Off',use_sudo=True, backup='') sed('/etc/apache2/apache2.conf',before='StartServers 2', after='StartServers 1', use_sudo=True, backup='') sed('/etc/apache2/apache2.conf',before='MaxClients 150', after='MaxClients 100', use_sudo=True, backup='') for module in env.APACHE_DISABLE_MODULES: sudo('rm -f /etc/apache2/mods-enabled/%s*'% module) #Install base python packages #We'll use easy_install at this stage since it doesn't download if the package #is current whereas pip always downloads. #Once both these packages mature we'll move to using the standard Ubuntu packages if (env.overwrite or not server_state('pip-venv-wrapper-installed')) and 'python-setuptools' in packages: sudo("easy_install virtualenv") sudo("easy_install pip") sudo("easy_install virtualenvwrapper") if env.verbosity: print " * easy installed pip, virtualenv, virtualenvwrapper" set_server_state('pip-venv-wrapper-installed') user_profile_dir = os.path.join(deployment_user_home(), ".profile") if not contains("source /usr/local/bin/virtualenvwrapper.sh", user_profile_dir): append("export WORKON_HOME=$HOME/env", user_profile_dir) append("source /usr/local/bin/virtualenvwrapper.sh", user_profile_dir) #cleanup after easy_install sudo("rm -rf build")
def upload_ssh_key(rollback=False): """ Upload your ssh key for passwordless logins """ user_ssh_dir = os.path.join(deployment_user_home(), '.ssh') auth_keys = os.path.join(user_ssh_dir, 'authorized_keys') if not rollback: local_user = getpass.getuser() host = socket.gethostname() u = '@'.join([local_user,host]) u = 'ssh-key-uploaded-%s'% u if not env.overwrite and server_state(u): return if not exists('.ssh'): run('mkdir .ssh') #determine local .ssh dir home = os.path.expanduser('~') ssh_dsa = os.path.join(home,'.ssh/id_dsa.pub') ssh_rsa = os.path.join(home,'.ssh/id_rsa.pub') if env.KEY_FILENAME: if not os.path.exists(env.KEY_FILENAME): print "ERROR: The specified KEY_FILENAME (or SSH_KEY_FILENAME) %s does not exist"% env.KEY_FILENAME sys.exit(1) else: ssh_key = env.KEY_FILENAME elif os.path.exists(ssh_dsa): ssh_key = ssh_dsa elif os.path.exists(ssh_rsa): ssh_key = ssh_rsa else: ssh_key = '' if ssh_key: ssh_file = open(ssh_key,'r').read() ssh_file = ssh_file.strip() # remove any trailing \n's if exists(auth_keys): _backup_file(auth_keys) if env.verbosity: print env.host, "UPLOADING SSH KEY" append(ssh_file,auth_keys) #append prevents uploading twice set_server_state(u) return else: if exists(auth_keys+'.wovenbak'): _restore_file(auth_keys) else: #no pre-existing keys remove the .ssh directory sudo('rm -rf ' + user_ssh_dir) return
def restrict_ssh(rollback=False): """ Set some sensible restrictions in Ubuntu /etc/ssh/sshd_config and restart sshd UseDNS no #prevents dns spoofing sshd defaults to yes X11Forwarding no # defaults to no AuthorizedKeysFile %h/.ssh/authorized_keys uncomments PasswordAuthentication no and restarts sshd """ if not rollback: if server_state('ssh_restricted'): return False sshd_config = '/etc/ssh/sshd_config' if env.verbosity: print env.host, "RESTRICTING SSH with "+sshd_config filename = 'sshd_config' if not exists(os.path.join(deployment_user_home(), '.ssh', 'authorized_keys')): #do not pass go do not collect $200 print env.host, 'You need to upload_ssh_key first.' return False _backup_file(sshd_config) context = {"HOST_SSH_PORT": env.HOST_SSH_PORT} upload_template('woven/ssh/sshd_config','/etc/ssh/sshd_config',context=context,use_sudo=True) # Restart sshd sudo('/etc/init.d/ssh restart') # The user can modify the sshd_config file directly but we save if (env.DISABLE_SSH_PASSWORD or env.INTERACTIVE) and contains('#PasswordAuthentication no','/etc/ssh/sshd_config',use_sudo=True): print "WARNING: You may want to test your node ssh login at this point ssh %s@%s -p%s"% (env.user, env.host, env.port) c_text = 'Would you like to disable password login and use only ssh key authentication' proceed = confirm(c_text,default=False) if not env.INTERACTIVE or proceed or env.DISABLE_SSH_PASSWORD: #uncomments PasswordAuthentication no and restarts uncomment(sshd_config,'#(\s?)PasswordAuthentication(\s*)no',use_sudo=True) sudo('/etc/init.d/ssh restart') set_server_state('ssh_restricted') return True else: #Full rollback _restore_file('/etc/ssh/sshd_config') if server_state('ssh_port_changed'): sed('/etc/ssh/sshd_config','Port '+ str(env.DEFAULT_SSH_PORT),'Port '+str(env.HOST_SSH_PORT),use_sudo=True) sudo('/etc/init.d/ssh restart') sudo('/etc/init.d/ssh restart') set_server_state('ssh_restricted', delete=True) return True
def disable_root(): """ Disables root and creates a new sudo user as specified by HOST_USER in your settings or your host_string The normal pattern for hosting is to get a root account which is then disabled. returns True on success """ def enter_password(): password1 = getpass.getpass(prompt='Enter the password for %s:'% sudo_user) password2 = getpass.getpass(prompt='Re-enter the password:'******'The password was not the same' enter_password() return password1 (olduser,host,port) = normalize(env.host_string) if env.verbosity and not (env.HOST_USER or env.ROLEDEFS): print "\nWOVEN will now walk through setting up your node (host).\n" if env.INTERACTIVE: root_user = prompt("\nWhat is the default administrator account for your node?", default=env.ROOT_USER) else: root_user = env.ROOT_USER if root_user == 'root': sudo_user = env.user else: sudo_user = root_user if env.INTERACTIVE: sudo_user = prompt("What is the new or existing account you wish to use to setup and deploy to your node?", default=sudo_user) else: root_user = env.ROOT_USER sudo_user = env.user original_password = env.get('HOST_PASSWORD','') host_string=join_host_strings(root_user,host,str(env.DEFAULT_SSH_PORT)) with settings(host_string=host_string, password=env.ROOT_PASSWORD): if not contains('sudo','/etc/group',use_sudo=True): sudo('groupadd sudo') home_path = deployment_user_home() if not exists(home_path): if env.verbosity: print env.host, 'CREATING A NEW ACCOUNT WITH SUDO PRIVILEGE: %s'% sudo_user if not original_password: original_password = enter_password() add_user(username=sudo_user, password=original_password,group='sudo') #Add existing user to sudo group else: sudo('adduser %s sudo'% sudo_user) #adm group used by Ubuntu logs sudo('usermod -a -G adm %s'% sudo_user) #add user to /etc/sudoers if not exists('/etc/sudoers.wovenbak',use_sudo=True): sudo('cp -f /etc/sudoers /etc/sudoers.wovenbak') sudo('cp -f /etc/sudoers /tmp/sudoers.tmp') append("# Members of the sudo group may gain root privileges", '/tmp/sudoers.tmp', use_sudo=True) append("%sudo ALL=(ALL) ALL", '/tmp/sudoers.tmp', use_sudo=True) sudo('visudo -c -f /tmp/sudoers.tmp') sudo('cp -f /tmp/sudoers.tmp /etc/sudoers') sudo('rm -rf /tmp/sudoers.tmp') env.password = original_password #finally disable root host_string=join_host_strings(sudo_user,host,str(env.DEFAULT_SSH_PORT)) with settings(host_string=host_string): if sudo_user <> root_user and root_user == 'root': if env.INTERACTIVE: d_root = confirm("Disable the root account", default=True) else: d_root = env.DISABLE_ROOT if d_root: if env.verbosity: print env.host, 'DISABLING ROOT' sudo("usermod -L %s"% 'root') return True