def test_ipv6_host_strings_join(self): """ join_host_strings() should use square brackets only for IPv6 and if port is given """ eq_(join_host_strings("user", "2001:DB8::1"), "user@2001:DB8::1") eq_(join_host_strings("user", "2001:DB8::1", "1222"), "user@[2001:DB8::1]:1222") eq_(join_host_strings("user", "192.168.0.0", "1222"), "[email protected]:1222")
def user(username): old_username, host, port = network.normalize(env.host_string) env.host_string = network.join_host_strings(username, host, port) yield env.host_string = network.join_host_strings(old_username, host, port)
def test_ipv6_host_strings_join(self): """ join_host_strings() should use square brackets only for IPv6 and if port is given """ eq_(join_host_strings('user', '2001:DB8::1'), 'user@2001:DB8::1') eq_(join_host_strings('user', '2001:DB8::1', '1222'), 'user@[2001:DB8::1]:1222') eq_(join_host_strings('user', '192.168.0.0', '1222'), '[email protected]:1222')
def get_password(user, host, port, login_only=False): from fabric.state import env from fabric.network import join_host_strings host_string = join_host_strings(user, host, port) sudo_password = env.sudo_passwords.get(host_string, env.sudo_password) login_password = env.passwords.get(host_string, env.password) return login_password if login_only else sudo_password or login_password
def run(self): conf = self.config fab_settings = { 'host_string': join_host_strings(conf['username'], conf['host'], port=conf['port']), } fab_settings.update({ key: val for key, val in conf.items() if key in ('password', 'key') }) cmds = ( 'mkdir -p ' + str(PurePath(conf['tar_name']).parent), self.build_command(), ) try: with settings(**fab_settings): for cmd in cmds: run(cmd) finally: disconnect_all()
def test_ipv6_host_strings_join(self): """ join_host_strings() should use square brackets only for IPv6 and if port is given """ eq_( join_host_strings('user', '2001:DB8::1'), 'user@2001:DB8::1' ) eq_( join_host_strings('user', '2001:DB8::1', '1222'), 'user@[2001:DB8::1]:1222' ) eq_( join_host_strings('user', '192.168.0.0', '1222'), '[email protected]:1222' )
def test_normalization_without_port(self): """ normalize() and join_host_strings() omit port if omit_port given """ eq_( join_host_strings(*normalize('user@localhost', omit_port=True)), 'user@localhost' )
def inner(self, *args, **kwargs): old_user, host, port = network.normalize(env.host_string) if not host: host, port = self.server.host, self.server.port env.service = self env.server = self.server with host_string(network.join_host_strings(user, host, port)): return func(self, *args, **kwargs)
def test_normalization_without_port(): """ normalize() and join_host_strings() omit port if omit_port given """ eq_( join_host_strings(*normalize('user@localhost', omit_port=True)), 'user@localhost' )
def __enter__(self): self.old_host_string = env.host_string env.host_string = join_host_strings(env.user, '127.0.0.1', self.local_port) env.host = '127.0.0.1' env.port = self.local_port self.start() env.tunnel = self return self
def __enter__(self): self.old_env = env.user, env.host, env.port, env.host_string env.host_string = join_host_strings(env.user, '127.0.0.1', self.local_port) env.host = '127.0.0.1' env.port = self.local_port self.start() env.tunnel = self return self
def change_ssh_port(rollback=False): """ This would be the first function to be run to setup a server. By changing the ssh port first we can test it to see if it has been changed, and thus can reasonably assume that root has also been disabled in a previous setupserver execution Returns success or failure """ if env.ROOT_DISABLED: return if not rollback: after = env.port before = str(env.DEFAULT_SSH_PORT) else: after = str(env.DEFAULT_SSH_PORT) before = env.port host = normalize(env.host_string)[1] host_string=join_host_strings('root',host,before) with settings(host_string=host_string, user='******', password=env.ROOT_PASSWORD): if env.verbosity: print env.host, "CHANGING SSH PORT TO: "+str(after) if not rollback: try: #Both test the port and also the ubuntu version. distribution, version = ubuntu_version() # print env.host, distribution, version if version < 9.10: print env.host, 'Woven is only compatible with Ubuntu versions 9.10 and greater' sys.exit(1) except KeyboardInterrupt: if env.verbosity: print >> sys.stderr, "\nStopped." sys.exit(1) except: #No way to catch the failing connection without catchall? print env.host, "Warning: Default port not responding.\n * Setupnode may already have been run previously or the host is down. Skipping ssh port.." return False sed('/etc/ssh/sshd_config','Port '+ str(before),'Port '+str(after),use_sudo=True) if env.verbosity: print env.host, "RESTARTING SSH on",after sudo('/etc/init.d/ssh restart') set_server_state('ssh_port_changed',object=str(before)) return True else: port = server_state('ssh_port_changed') if port: sed('/etc/ssh/sshd_config','Port '+ str(before),'Port '+str(after),use_sudo=True) set_server_state('ssh_port_changed',delete=True) sudo('/etc/init.d/ssh restart') return True return False
def connect_host(dest, server): config = get_config(dest) dns = config.get(server, 'dns') user = config.get(server, 'user') key_filename = config.get(server, 'key_filename') if config.has_option(server, 'key_filename') else None password = config.get(server, 'password') if config.has_option(server, 'password') else None if not key_filename and not password: safe_exit("Cann't find key_filename or password in %s %s config file.\n"%(dest, server), 1, sys.stderr) env.host_string = join_host_strings(user, dns) env.password = password env.key_filename = key_filename
def tune_env(config, *_, **__): # noqa for params in config.values(): host_string = join_host_strings(params['USER'], params['HOST'], params.get('PORT')) env.hosts.append(host_string) env.connection_attempts = ATTEMPTS if env.key_filename is None: env.key_filename = [params['KEY_PATH']] else: env.key_filename.append(params['KEY_PATH']) env['{}_project_dir'.format(host_string)] = params['PROJECT_DIR']
def setup_host(cp, server): host = cp.get(server, 'dns') user = cp.get(server, 'user') if cp.has_option(server, 'user') else None port = cp.getint(server, 'port') if cp.has_option(server, 'port') else None host_string = join_host_strings(user, host, port) if user or port else host env.port = port env.host_string = host_string password = cp.get(server, 'password') if cp.has_option(server, 'password') else None keyfile = cp.get(server, 'keyfile') if cp.has_option(server, 'keyfile') else None if password: env.password = password env.passwords[host_string] = password if keyfile: env.key_filename = keyfile
def teardown_disable_root(): local('rm -rf .woven') with settings(host_string='[email protected]:22',user='******',password='******'): run('echo %s:%s > /tmp/root_user.txt'% ('root','root')) sudo('chpasswd < /tmp/root_user.txt') sudo('rm -rf /tmp/root_user.txt') print "Closing connection %s"% env.host_string #print connections connections[env.host_string].close() try: connections['[email protected]:22'].close() except: pass original_username = '******' (olduser,host,port) = normalize(env.host_string) host_string=join_host_strings('root',host,'22') with settings(host_string=host_string, password='******'): sudo('deluser --remove-home '+original_username)
def change_ssh_port(): """ For security woven changes the default ssh port. """ host = normalize(env.host_string)[1] after = env.port before = str(env.DEFAULT_SSH_PORT) host_string = join_host_strings(env.user, host, before) with settings(host_string=host_string, user=env.user): if env.verbosity: print env.host, "CHANGING SSH PORT TO: " + str(after) sed("/etc/ssh/sshd_config", "Port " + str(before), "Port " + str(after), use_sudo=True) if env.verbosity: print env.host, "RESTARTING SSH on", after sudo("/etc/init.d/ssh restart") return True
def teardown_disable_root(): local('rm -rf .woven') with settings(host_string='[email protected]:22', user='******', password='******'): run('echo %s:%s > /tmp/root_user.txt' % ('root', 'root')) sudo('chpasswd < /tmp/root_user.txt') sudo('rm -rf /tmp/root_user.txt') print "Closing connection %s" % env.host_string #print connections connections[env.host_string].close() try: connections['[email protected]:22'].close() except: pass original_username = '******' (olduser, host, port) = normalize(env.host_string) host_string = join_host_strings('root', host, '22') with settings(host_string=host_string, password='******'): sudo('deluser --remove-home ' + original_username)
def change_ssh_port(): """ For security woven changes the default ssh port. """ host = normalize(env.host_string)[1] after = env.port before = str(env.DEFAULT_SSH_PORT) host_string=join_host_strings(env.user,host,before) with settings(host_string=host_string, user=env.user): if env.verbosity: print env.host, "CHANGING SSH PORT TO: "+str(after) sed('/etc/ssh/sshd_config','Port '+ str(before),'Port '+str(after),use_sudo=True) if env.verbosity: print env.host, "RESTARTING SSH on",after sudo('/etc/init.d/ssh restart') return True
def __getitem__(self, key): gw = s.env.get('gateway') if gw is None: return super(GatewayConnectionCache, self).__getitem__(key) gw_user, gw_host, gw_port = network.normalize(gw) if self._gw is None: # Normalize given key (i.e. obtain username and port, if not given) self._gw = network.connect(gw_user, gw_host, gw_port) # Normalize given key (i.e. obtain username and port, if not given) user, host, port = network.normalize(key) # Recombine for use as a key. real_key = network.join_host_strings(user, host, port) # If not found, create new connection and store it if real_key not in self: self[real_key] = connect_forward(self._gw, host, port, user) # Return the value either way return dict.__getitem__(self, real_key)
def __getitem__(self, key): gw = s.env.get('gateway') if gw is None: return super(GatewayConnectionCache, self).__getitem__(key) gw_user, gw_host, gw_port = network.normalize(gw) if self._gw is None: # Normalize given key (i.e. obtain username and port, if not given) self._gw = network.connect(gw_user, gw_host, gw_port, None, False) # Normalize given key (i.e. obtain username and port, if not given) user, host, port = network.normalize(key) # Recombine for use as a key. real_key = network.join_host_strings(user, host, port) # If not found, create new connection and store it if real_key not in self: self[real_key] = connect_forward(self._gw, host, port, user) # Return the value either way return dict.__getitem__(self, real_key)
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 = '/home/%s'% sudo_user 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
def get_password(user, host, port): from fabric.state import env from fabric.network import join_host_strings host_string = join_host_strings(user, host, port) return env.passwords.get(host_string, env.password)
def set_password(user, host, port, password): from fabric.state import env from fabric.network import join_host_strings host_string = join_host_strings(user, host, port) env.password = env.passwords[host_string] = password
def inner(*args, **kwargs): old_user, host, port = network.normalize(env.host_string) env.host_string = network.join_host_strings(user, host, port) result = func(*args, **kwargs) env.host_string = network.join_host_strings(old_user, host, port) return result
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 host = normalize(env.host_string)[1] 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 env.user != "root": sudo_user = env.user else: sudo_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, key_filename=env.key_filename, password=env.ROOT_PASSWORD): if not contains("/etc/group", "sudo", use_sudo=True): sudo("groupadd sudo") home_path = "/home/%s" % sudo_user 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("/tmp/sudoers.tmp", "# Members of the sudo group may gain root privileges", use_sudo=True) append("/tmp/sudoers.tmp", "%sudo ALL=(ALL) NOPASSWD:ALL", use_sudo=True) sudo("visudo -c -f /tmp/sudoers.tmp") sudo("cp -f /tmp/sudoers.tmp /etc/sudoers") sudo("rm -rf /tmp/sudoers.tmp") if env.key_filename: sudo("mkdir -p /home/%s/.ssh" % sudo_user) sudo("cp -f ~/.ssh/authorized_keys " "/home/%s/.ssh/authorized_keys" % sudo_user) sudo("chown -R %s:sudo /home/%s/.ssh" % (sudo_user, sudo_user)) 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
def _to_user(user): return join_host_strings(user, env.host, env.port)
def disable_root(rollback=False): """ 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. If root is disabled as it is in the default ubuntu install then set ROOT_DISABLED:True in your settings returns True on success """ if env.ROOT_DISABLED: return def enter_password(): password1 = prompt('Enter the password for %s:'% original_username) password2 = prompt('Re-enter the password:'******'The password was not the same' enter_password() return password1 if not rollback: #TODO write a test in paramiko to see whether root has already been disabled #Fabric doesn't have a way of detecting a login fail which would be the best way #that we could assume that root has been disabled #print env.host, 'settings:', env.host_string, env.user, env.port original_username = env.user original_password = env.get('HOST_PASSWORD','') (olduser,host,port) = normalize(env.host_string) host_string=join_host_strings('root',host,str(port)) with settings(host_string=host_string, password=env.ROOT_PASSWORD): if not contains('sudo','/etc/group',use_sudo=True): sudo('groupadd sudo') set_server_state('sudo-added') home_path = '/home/%s'% original_username if not exists(home_path, use_sudo=True): if env.verbosity: print env.host, 'CREATING A NEW ACCOUNT: %s'% original_username if not original_password: original_password = enter_password() add_user(username=original_username, password=original_password,group='sudo') #adm group used by Ubuntu logs sudo('usermod -a -G adm %s'% original_username) #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') #Add existing user to sudo group else: sudo('adduser %s sudo'% original_username) env.password = original_password #finally disable root if env.verbosity: print env.host, 'DISABLING ROOT' sudo("usermod -L %s"% 'root') return True else: #rollback to root if not env.ROOT_PASSWORD: env.ROOT_PASSWORD = enter_password() run('echo %s:%s > /tmp/root_user.txt'% ('root',env.ROOT_PASSWORD)) sudo('chpasswd < /tmp/root_user.txt') sudo('rm -rf /tmp/root_user.txt') print "Closing connection %s"% env.host_string connections[env.host_string].close() original_username = env.user (olduser,host,port) = normalize(env.host_string) host_string=join_host_strings('root',host,str(env.port)) with settings(host_string=host_string, password=env.ROOT_PASSWORD): if env.INTERACTIVE: c_text = 'CAUTION: Woven will now delete the user %s and the home directory. \n'% original_username c_text = 'Please ensure you can login as root before continuing.\n' c_text += 'Do you wish to continue:' proceed = confirm(c_text,default=False) if not env.INTERACTIVE or proceed: sudo('deluser --remove-home '+original_username) if server_state('sudo-added'): #never true on default installation sudo('groupdel sudo') set_server_state('sudo-added',delete=True)
def inner(self, *args, **kwargs): env.server = self with host_string(network.join_host_strings(user, self.host, self.port)): return func(self, *args, **kwargs)
def host_string(host_entry): """compile host string from a (parsed) host_entry.""" return fnw.join_host_strings(host_entry['user'], host_entry['address'], host_entry['port'])