def full_unforward(to_ip, host_interface, src): """ Removes the rule made by full_forward command :param to_ip: ip to which packets have been forwarded :param host_interface: interface receiving packets :param src: packet source ip :return: None """ delete_command = IptablesHelper.FORWARD_RULE_TEMPLATE.format(host_interface, to_ip, IptablesHelper.DELETE, src) logged_console_call(delete_command)
def list_call(not_fancy, unprivileged): """ Makes a call to lxc-ls listing all the containers :param not_fancy: if the output needs to be concise :param unprivileged: if the container is unprivileged :return: None """ privilege_string = 'sudo ' if not unprivileged else '' command = privilege_string + 'lxc-ls {0}'.format('' if not_fancy else '-f') logged_console_call(command)
def unforward_port(to_ip, to_port, host_port, host_interface, src): """ Removes the rule made by forward_port command :param to_ip: ip to which the packets are forwarded :param to_port: port to which the packets are forwarded :param host_port: ip receiving the packets :param host_interface: port receiving the packets :param src: packet source ip :return: None """ delete_command = IptablesHelper.FORWARD_PORT_RULE_TEMPLATE.format( host_interface, host_port, to_ip, to_port, IptablesHelper.DELETE, src ) logged_console_call(delete_command)
def full_forward(to_ip, host_interface, src, check=True): """ Makes a rule, forwarding all packets from *host_interface* to *to_ip* :parameter to_ip: ip to which packets will be forwarded :parameter host_interface: interface receiving packets :parameter src: packet source ip :parameter check: whether to check for existence of the rule before making one :return: None """ add_command = IptablesHelper.FORWARD_RULE_TEMPLATE.format(host_interface, to_ip, IptablesHelper.ADD, src) if check and not IptablesHelper.__check_if_forward_rule_exists(to_ip, host_interface, src): logged_console_call(add_command) else: logging.info("No rule was added due to checking enabled")
def list(): """ Outputs nat table of iptables :return: if listing was successful """ list_command = IptablesHelper.NAT_RULE_TEMPLATE + IptablesHelper.LIST return logged_console_call(list_command) == 0
def flush(): """ Flushes nat table of iptables :return: if flushing was successful """ flush_command = IptablesHelper.NAT_RULE_TEMPLATE + IptablesHelper.FLUSH return logged_console_call(flush_command) == 0
def prepare_unprivileged_config(uid_string, gid_string, network_devices_number, user): """ Performs procedures without which unprivileged container creation is impossible :param uid_string: string with user ids starting "from-to" :param gid_string: string with group ids starting "from-to" :param network_devices_number: number of network devices available for unprivileged containers :param user: user, who gets the devices :return: None """ def split_uids_guids(input_string): """ Splits the string in the format "from-to" into two integers list :param input_string: the string in the format "from-to" :return: list of numbers """ return split_to_function(input_string, '-', int) ConsoleHelper.__ensure_unprivileged_dirs_exist() uid_start, uid_stop = split_uids_guids(uid_string) gid_start, gid_stop = split_uids_guids(gid_string) uid_count = uid_stop - uid_start gid_count = gid_stop - gid_start if not user: user = getuser() ConsoleHelper.__assign_uids_to_user(uid_start, uid_stop, user) ConsoleHelper.__assign_gids_to_user(gid_start, gid_stop, user) ConsoleHelper.__make_home_dir_executable() Config.create_dirs_for_unprivileged_container() if not path.exists(Config.UNPRIVILEGED_CONTAINER_CONFIG_PATH): copyfile(Config.default_unprivileged_config_resource_path(), Config.UNPRIVILEGED_CONTAINER_CONFIG_PATH) with LxcConfig(Config.UNPRIVILEGED_CONTAINER_CONFIG_PATH) as config_file: config_file.set_value(ConsoleHelper.LXC_ID_MAP_KEY, 'u 0 {0} {1}'.format(uid_start, uid_count)) config_file.append_value(ConsoleHelper.LXC_ID_MAP_KEY, 'g 0 {0} {1}'.format(gid_start, gid_count)) # Adds slots for network devices in unprivileged containers logged_console_call('echo ' + '"{0} veth lxcbr0 {1}"'.format(user, network_devices_number) + ' | sudo tee -a {0}'.format('/etc/lxc/lxc-usernet'), mute=True) # Following line gives everyone write permissions into container backing store path logged_console_call('sudo chmod a+w ' + Config.lxc_backing_store_path(True)) logging.info('Prepared uids {0} and gids {1} for unprivileged usage'. format(uid_string, gid_string))
def mount_backing_store_device(device, filesystem, unprivileged, option_input_string=''): """ Mounts the *device* into a directory considering if container *unprivileged* with a set of options :param device: device to be mounted :param filesystem: filesystem of the device :param unprivileged: if the container is unprivileged :param option_input_string: string of options :return: None """ mount_path = Config.lxc_backing_store_path(unprivileged) makedirs(mount_path, exist_ok=True) option_set = set([option.strip() for option in option_input_string.split()]) if unprivileged: # Fixes the notification while deleting btrfs backed storage in unpriv. container # applied to any unpriv. container w/o thinking about backing storage, BAD # FIXME option_set.add('user_subvol_rm_allowed') option_string = '-o {0}'.format(','.join(option_set)) if len(option_set) else '' logged_console_call('sudo mount -t {0} {1} {2} {3}'.format(filesystem, device, mount_path, option_string))
def remove_call(name, unprivileged): """ Makes a call to lxc-destroy ot remove a container :param name: name of the container in question :param unprivileged: if the container is unprivileged :return: None """ privilege_string = 'sudo ' if not unprivileged else '' if logged_console_call(privilege_string + 'lxc-destroy -n {0}'.format(name)) == 0: LxcHelper.__remember_remove(name) logging.info('Removed container {0}'.format(name))
def forward_port(to_ip, to_port, host_port, host_interface, src, check=True): """ Makes a rule, forwarding a packets from a single *host_port* to a single *to_port* of the receiver with *to_ip* :param to_ip: ip to which the packets are forwarded :param to_port: port to which the packets are forwarded :param host_port: ip receiving the packets :param host_interface: port receiving the packets :param src: packet source ip :param check: whether to check for existence of the rule before making one :return: None """ add_command = IptablesHelper.FORWARD_PORT_RULE_TEMPLATE.format( host_interface, host_port, to_ip, to_port, IptablesHelper.ADD, src ) if ( check and not IptablesHelper.__check_if_port_forward_rule_exists(to_ip, to_port, host_port, host_interface, src) or not check ): logged_console_call(add_command) else: logging.info("No rule was added due to checking enabled")
def copy_call(original_name, new_name, unprivileged): """ Makes a call to lxc-clone making a COW copy of the container :param original_name: name of the old container :param new_name: name of the copy :param unprivileged: if the container is unprivileged :return: None """ privilege_string = 'sudo ' if not unprivileged else '' command = privilege_string + 'lxc-clone -s -o {0} -n {1}'.format(original_name, new_name) if logged_console_call(command) == 0: LxcHelper.__remember_copy(original_name, new_name) logging.info('Made a snapshot of {0} into {1}'.format(original_name, new_name))
def create_call(name, backing_store, distro, release, arch, unprivileged): """ Makes a call to lxc-create to create a container :param name: name of the new container :param backing_store: backing store of the new container :param distro: distribution from which the container is created :param release: release of the distro from which the container is created :param arch: architecture on which the container is created :param unprivileged: if the container is unprivileged :return: None """ privilege_string = 'sudo ' if not unprivileged else '' command = privilege_string + 'lxc-create -n {0} -B {1} -t download -- -d {2} -r {3} -a {4}'. \ format(name, backing_store, distro, release, arch) if logged_console_call(command) == 0: LxcHelper.__remember_create(name) logging.info('Created {5} container {0} with backing store {1} as ({2}, {3}, {4})'. format(name, backing_store, distro, release, arch, 'privileged' if not unprivileged else 'unprivileged'))
def __make_home_dir_executable(): logged_console_call('sudo chmod +x $HOME')
def __assign_gids_to_user(ids_start, ids_stop, user='******'): logged_console_call('sudo usermod --add-subgids {0}-{1} {2}'.format(ids_start, ids_stop, user))
def __check_if_port_forward_rule_exists(to_ip, to_port, host_port, host_interface, src): check_command = IptablesHelper.FORWARD_PORT_RULE_TEMPLATE.format( host_interface, host_port, to_ip, to_port, IptablesHelper.CHECK, src ) return logged_console_call(check_command, mute=True) == 0