From 96e2cefc664d8e32b8e96c5fdb37a8271b832160 Mon Sep 17 00:00:00 2001 From: tschettervictor Date: Sat, 4 Jan 2025 11:12:56 -0700 Subject: [PATCH 001/141] etcupdate: beta version Add subcommand "etcupdate" This will simply use the built in "bootstrap" command to bootstrap the "src" version of a release, then create a tarball for it ONCE. This tarball is then used to update (includes dry run) a specifie jail to a specified RELEASE version of etc. --- usr/local/bin/bastille | 3 +- usr/local/share/bastille/etcupdate.sh | 128 ++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 usr/local/share/bastille/etcupdate.sh diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index 5c78318a..6e33fe10 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -93,6 +93,7 @@ Available Commands: create Create a new thin container or a thick container if -T|--thick option specified. destroy Destroy a stopped container or a FreeBSD release. edit Edit container configuration files (advanced). + etcupdate Update /etc directory to specified release. export Exports a specified container. help Help about any command. htop Interactive process viewer (requires htop). @@ -157,7 +158,7 @@ version|-v|--version) help|-h|--help) usage ;; -bootstrap|create|destroy|export|htop|import|list|mount|rdr|restart|setup|start|top|umount|update|upgrade|verify) +bootstrap|create|destroy|etcupdate|export|htop|import|list|mount|rdr|restart|setup|start|top|umount|update|upgrade|verify) # Nothing "extra" to do for these commands. -- cwells ;; clone|config|cmd|console|convert|cp|edit|limits|pkg|rcp|rename|service|stop|sysrc|tags|template|zfs) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh new file mode 100644 index 00000000..ec805726 --- /dev/null +++ b/usr/local/share/bastille/etcupdate.sh @@ -0,0 +1,128 @@ +#!/bin/sh +# Copyright (c) 2018-2024, Christer Edwards +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +. /usr/local/share/bastille/common.sh +. /usr/local/etc/bastille/bastille.conf + +usage() { + error_notify "Usage: bastille etcupdate [option(s)] [TARGET|bootstrap] RELEASE" + cat << EOF + Options: + + -d | --dry-run Show output, but do not apply. + +EOF + exit 1 +} + +bootstrap_etc_release() { + local _release="${1}" + local _current="$(sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives | awk -F': ' '{print $2}')" + if ! ls -A "${bastille_releasesdir}/${_release}/usr/src" 2>/dev/null; then + sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives=src + if ! bastille bootstrap "${_release}"; then + error_notify "Failed to bootstrap etcupdate \"${_release}\"" + fi + sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}" + fi +} + +bootstrap_etc_tarball() { + local _release="${1}" + if [ ! -f ${bastille_cachedir}/${_release}.tbz2 ]; then + if ! etcupdate build -d /tmp/etcupdate -s ${bastille_releasesdir}/${_release}/usr/src ${bastille_cachedir}/${_release}.tbz2; then + error_exit "Failed to build etcupdate tarball \"${_release}.tbz2\"" + else + info "Etcupdate bootstrap complete: \"${_release}\"" + fi + else + info "Etcupdate release has already been prepared for application: \"${_release}\"" + exit 0 + fi +} + +update_jail_etc() { + local _jail="${1}" + local _release="${2}" + if [ "${DRY_RUN}" -eq 1 ]; then + info "[_jail]: --dry-run" + etcupdate -n -D "${bastille_jailsdir}"/"${_jail}"/root -t ${bastille_cachedir}/${_release}.tbz2 + else + info "[_jail]:" + etcupdate -D "${bastille_jailsdir}"/"${_jail}"/root -t ${bastille_cachedir}/${_release}.tbz2 + fi +} + +if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then + usage +fi + +# Handle options. +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -d|--dry-run) + if [ -z "${2}" ] || [ -z "${3}" ]; then + usage + else + DRY_RUN=1 + shift + fi + ;; + -*) + error_exit "Unknown option: \"${1}\"" + ;; + bootstrap) + if [ -z "${2}" ]; then + usage + else + RELEASE="${2}" + bootstrap_etc_release "${RELEASE}" + bootstrap_etc_tarball "${RELEASE}" + shift $# + fi + ;; + *) + if [ -z "${2}" ]; then + usage + else + TARGET="${1}" + RELEASE="${2}" + fi + if [ -z "${DRY_RUN}" ]; then + DRY_RUN=0 + fi + set_target_single "${TARGET}" + update_jail_etc "${TARGET}" "${RELEASE}" + shift "$#" + ;; + esac +done From bb7f73e8f662347b5ea314a79282ba09e472236e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 5 Jan 2025 19:10:59 -0700 Subject: [PATCH 002/141] bastille: rename functions to "old" in place of new ones Rename "check_target_is_running" and "target_all_jails" to have the suffix "_old". These two function are only ever called from within the main bastille executable. I am integrating these functions in "common.sh" so renaming them here for removal in the future is the best path forward. --- usr/local/bin/bastille | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index 5c78318a..2ef949d7 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -131,7 +131,7 @@ EOF CMD=$1 shift -target_all_jails() { +target_all_jails_old() { _JAILS=$(/usr/sbin/jls name) JAILS="" for _jail in ${_JAILS}; do @@ -142,7 +142,7 @@ target_all_jails() { done } -check_target_is_running() { +check_target_is_running_old() { if [ ! "$(/usr/sbin/jls name | awk "/^${TARGET}$/")" ]; then error_exit "[${TARGET}]: Not started. See 'bastille start ${TARGET}'." fi @@ -157,10 +157,10 @@ version|-v|--version) help|-h|--help) usage ;; -bootstrap|create|destroy|export|htop|import|list|mount|rdr|restart|setup|start|top|umount|update|upgrade|verify) +bootstrap|console|create|destroy|export|htop|import|list|mount|rdr|restart|setup|start|top|umount|update|upgrade|verify) # Nothing "extra" to do for these commands. -- cwells ;; -clone|config|cmd|console|convert|cp|edit|limits|pkg|rcp|rename|service|stop|sysrc|tags|template|zfs) +clone|config|cmd|convert|cp|edit|limits|pkg|rcp|rename|service|stop|sysrc|tags|template|zfs) # Parse the target and ensure it exists. -- cwells if [ $# -eq 0 ]; then # No target was given, so show the command's help. -- cwells PARAMS='help' @@ -181,15 +181,15 @@ clone|config|cmd|console|convert|cp|edit|limits|pkg|rcp|rename|service|stop|sysr fi if [ "${TARGET}" = 'ALL' ]; then - target_all_jails + target_all_jails_old elif [ "${CMD}" = "pkg" ] && [ "${TARGET}" = '-H' ] || [ "${TARGET}" = '--host' ]; then TARGET="${1}" USE_HOST_PKG=1 if [ "${TARGET}" = 'ALL' ]; then - target_all_jails + target_all_jails_old else JAILS="${TARGET}" - check_target_is_running + check_target_is_running_old fi shift elif [ "${CMD}" = 'template' ] && [ "${TARGET}" = '--convert' ]; then @@ -205,8 +205,8 @@ clone|config|cmd|console|convert|cp|edit|limits|pkg|rcp|rename|service|stop|sysr fi case "${CMD}" in - cmd|console|pkg|service|stop|sysrc|template) - check_target_is_running + cmd|pkg|service|stop|sysrc|template) + check_target_is_running_old ;; convert|rename) # Require the target to be stopped. -- cwells From dbd303fa2e9bcce9c182391ac178df4fc03f453c Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 5 Jan 2025 19:14:15 -0700 Subject: [PATCH 003/141] common.sh: integrate new functions These are all the new function I am beginning to move to common.sh for use with all jails. --- usr/local/share/bastille/common.sh | 253 ++++++++++++++++++++--------- 1 file changed, 177 insertions(+), 76 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index b9b0986f..bb3782d6 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -28,7 +28,6 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# Source config file . /usr/local/etc/bastille/bastille.conf COLOR_RED= @@ -48,24 +47,30 @@ enable_color() { . /usr/local/share/bastille/colors.pre.sh } +enable_debug() { + # Enable debug mode. + warn "***DEBUG MODE START***" + set -x +} + # If "NO_COLOR" environment variable is present, or we aren't speaking to a # tty, disable output colors. if [ -z "${NO_COLOR}" ] && [ -t 1 ]; then enable_color fi -# Error/Info functions -error_notify() { - echo -e "${COLOR_RED}$*${COLOR_RESET}" 1>&2 -} - +# Notify message on error, and continue to next jail error_continue() { error_notify "$@" - # Disabling this shellcheck as we only ever call it inside of a loop # shellcheck disable=SC2104 continue } +# Notify message on error, but do not exit +error_notify() { + echo -e "${COLOR_RED}$*${COLOR_RESET}" 1>&2 +} + # Notify message on error and exit error_exit() { error_notify "$@" @@ -82,7 +87,8 @@ warn() { check_target_exists() { local _TARGET="${1}" - if [ ! -d "${bastille_jailsdir}"/"${_TARGET}" ]; then + local _jaillist="$(bastille list jails)" + if ! echo "${_jaillist}" | grep -Eq "^${_TARGET}$"; then return 1 else return 0 @@ -91,7 +97,7 @@ check_target_exists() { check_target_is_running() { local _TARGET="${1}" - if [ ! "$(/usr/sbin/jls name | awk "/^${_TARGET}$/")" ]; then + if ! jls name | grep -Eq "^${_TARGET}$"; then return 1 else return 0 @@ -100,13 +106,109 @@ check_target_is_running() { check_target_is_stopped() { local _TARGET="${1}" - if [ "$(/usr/sbin/jls name | awk "/^${_TARGET}$/")" ]; then + if jls name | grep -Eq "^${_TARGET}$"; then return 1 else return 0 fi } +get_jail_name() { + local _JID="${1}" + local _jailname="$(jls -j ${_JID} name 2>/dev/null)" + if [ -z "${_jailname}" ]; then + return 1 + else + echo "${_jailname}" + fi +} + +jail_autocomplete() { + local _TARGET="${1}" + local _jaillist="$(bastille list jails)" + local _AUTOTARGET="$(echo "${_jaillist}" | grep -E "^${_TARGET}")" + if [ -n "${_AUTOTARGET}" ]; then + if [ "$(echo "${_AUTOTARGET}" | wc -l)" -eq 1 ]; then + echo "${_AUTOTARGET}" + else + error_continue "Multiple jails found for ${_TARGET}:\n${_AUTOTARGET}" + return 1 + fi + else + return 2 + fi +} + +set_target() { + local _TARGET=${1} + JAILS="" + TARGET="" + if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then + target_all_jails + else + for _jail in ${_TARGET}; do + if echo "${_jail}" | grep -Eq '^[0-9]+$'; then + if get_jail_name "${_jail}" > /dev/null; then + _jail="$(get_jail_name ${_jail})" + else + error_continue "Error: JID \"${_jail}\" not found. Is jail running?" + fi + elif ! check_target_exists "${_jail}"; then + if jail_autocomplete "${_jail}" > /dev/null; then + _jail="$(jail_autocomplete ${_jail})" + elif [ $? -eq 2 ]; then + error_continue "Jail not found \"${_jail}\"" + else + exit 1 + fi + fi + TARGET="${TARGET} ${_jail}" + JAILS="${JAILS} ${_jail}" + export TARGET + export JAILS + done + fi +} + +set_target_single() { + local _TARGET="${1}" + local _status=0 + if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then + error_exit "[all|ALL] not supported with this command." + elif echo "${_TARGET}" > /dev/null | grep -Eq '^[0-9]+$'; then + if get_jail_name "${_TARGET}" > /dev/null; then + _TARGET="$(get_jail_name ${_TARGET})" + else + error_exit "Error: JID \"${_TARGET}\" not found. Is jail running?" + fi + elif + ! check_target_exists "${_TARGET}"; then + if jail_autocomplete "${_TARGET}" > /dev/null; then + _TARGET="$(jail_autocomplete ${_TARGET})" + elif [ $? -eq 2 ]; then + error_exit "Jail not found \"${_jail}\"" + else + exit 1 + fi + else + TARGET="${_TARGET}" + JAILS="${_TARGET}" + export TARGET + export JAILS + fi +} + +target_all_jails() { + local _JAILS="$(bastille list jails)" + JAILS="" + for _jail in ${_JAILS}; do + if [ -d "${bastille_jailsdir}/${_jail}" ]; then + JAILS="${JAILS} ${_jail}" + fi + done + export JAILS +} + generate_static_mac() { local jail_name="${1}" local external_interface="${2}" @@ -121,47 +223,74 @@ generate_static_mac() { } generate_vnet_jail_netblock() { - local jail_name="$1" - local use_unique_bridge="$2" - local external_interface="$3" - generate_static_mac "${jail_name}" "${external_interface}" - ## determine number of containers + 1 + local jail_name="${1}" + local use_unique_bridge="${2}" + local external_interface="${3}" + # setting this to 1 temprarily until we integrate the -M switch + local static_mac=1 + ## determine number of interfaces + 1 ## iterate num and grep all jail configs ## define uniq_epair - local jail_list="$(bastille list jails)" - if [ -n "${jail_list}" ]; then - local list_jails_num="$(echo "${jail_list}" | wc -l | awk '{print $1}')" - local num_range=$((list_jails_num + 1)) - for _num in $(seq 0 "${num_range}"); do - if ! grep -q "e[0-9]b_bastille${_num}" "${bastille_jailsdir}"/*/jail.conf; then - if ! grep -q "epair${_num}" "${bastille_jailsdir}"/*/jail.conf; then - local uniq_epair="bastille${_num}" + local _epair_if_count="$(grep -Eos 'epair[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local _vnet_if_count="$(grep -Eos 'bastille[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local epair_num_range=$((_epair_if_count + 1)) + local vnet_num_range=$((_vnet_if_count + 1)) + if [ -n "${use_unique_bridge}" ]; then + if [ "${_epair_if_count}" -gt 0 ]; then + for _num in $(seq 0 "${epair_num_range}"); do + if ! grep -Eosq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then local uniq_epair_bridge="${_num}" break fi - fi - done + done + else + local uniq_epair_bridge="0" + fi else - local uniq_epair="bastille0" - local uniq_epair_bridge="0" + if [ "${_vnet_if_count}" -gt 0 ]; then + for _num in $(seq 0 "${vnet_num_range}"); do + if ! grep -Eosq "bastillle${_num}" ${bastille_jailsdir}/*/jail.conf; then + local uniq_epair="bastille${_num}" + break + fi + done + else + local uniq_epair="bastille0" + fi fi + ## If BRIDGE is enabled, generate bridge config, else generate VNET config if [ -n "${use_unique_bridge}" ]; then - ## generate bridge config - cat <<-EOF + if [ -n "${static_mac}" ]; then + ## Generate bridged VNET config with static MAC address + generate_static_mac "${jail_name}" "${external_interface}" + cat <<-EOF vnet; - vnet.interface = e${uniq_epair_bridge}b_${jail_name}; + vnet.interface = epair${uniq_epair_bridge}b; exec.prestart += "ifconfig epair${uniq_epair_bridge} create"; exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}a up name e${uniq_epair_bridge}a_${jail_name}"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}b up name e${uniq_epair_bridge}b_${jail_name}"; - exec.prestart += "ifconfig e${uniq_epair_bridge}a_${jail_name} ether ${macaddr}a"; - exec.prestart += "ifconfig e${uniq_epair_bridge}b_${jail_name} ether ${macaddr}b"; - exec.poststop += "ifconfig ${external_interface} deletem e${uniq_epair_bridge}a_${jail_name}"; - exec.poststop += "ifconfig e${uniq_epair_bridge}a_${jail_name} destroy"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}a ether ${macaddr}a"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}b ether ${macaddr}b"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}a description \"vnet host interface for Bastille jail ${jail_name}\""; + exec.poststop += "ifconfig ${external_interface} deletem epair${uniq_epair_bridge}a"; + exec.poststop += "ifconfig epair${uniq_epair_bridge}a destroy"; EOF + else + ## Generate bridged VNET config without static MAC address + cat <<-EOF + vnet; + vnet.interface = epair${uniq_epair_bridge}b; + exec.prestart += "ifconfig epair${uniq_epair_bridge} create"; + exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}a description \"vnet host interface for Bastille jail ${jail_name}\""; + exec.poststop += "ifconfig ${external_interface} deletem epair${uniq_epair_bridge}a"; + exec.poststop += "ifconfig epair${uniq_epair_bridge}a destroy"; +EOF + fi else - ## generate config - cat <<-EOF + if [ -n "${static_mac}" ]; then + ## Generate VNET config with static MAC address + generate_static_mac "${jail_name}" "${external_interface}" + cat <<-EOF vnet; vnet.interface = e0b_${uniq_epair}; exec.prestart += "jib addm ${uniq_epair} ${external_interface}"; @@ -170,44 +299,17 @@ EOF exec.prestart += "ifconfig e0a_${uniq_epair} description \"vnet host interface for Bastille jail ${jail_name}\""; exec.poststop += "jib destroy ${uniq_epair}"; EOF - fi -} - -set_target() { - local _TARGET="${1}" - if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then - target_all_jails - else - check_target_exists "${_TARGET}" || error_exit "Jail not found \"${_TARGET}\"" - JAILS="${_TARGET}" - TARGET="${_TARGET}" - export JAILS - export TARGET - fi -} - -set_target_single() { - local _TARGET="${1}" - if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then - error_exit "[all|ALL] not supported with this command." - else - check_target_exists "${_TARGET}" || error_exit "Jail not found \"${_TARGET}\"" - JAILS="${_TARGET}" - TARGET="${_TARGET}" - export JAILS - export TARGET - fi -} - -target_all_jails() { - local _JAILS="$(bastille list jails)" - JAILS="" - for _jail in ${_JAILS}; do - if [ -d "${bastille_jailsdir}/${_jail}" ]; then - JAILS="${JAILS} ${_jail}" + else + ## Generate VNET config without static MAC address + cat <<-EOF + vnet; + vnet.interface = e0b_${uniq_epair}; + exec.prestart += "jib addm ${uniq_epair} ${external_interface}"; + exec.prestart += "ifconfig e0a_${uniq_epair} description \"vnet host interface for Bastille jail ${jail_name}\""; + exec.poststop += "jib destroy ${uniq_epair}"; +EOF fi - done - export JAILS + fi } checkyesno() { @@ -230,4 +332,3 @@ checkyesno() { ;; esac } - From 5017ad012021a90a2ffc6db259c180c9e6d2eb08 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 5 Jan 2025 19:21:29 -0700 Subject: [PATCH 004/141] console: new update This makes console act with the new common.sh file. Enable debug mode Allow console by JID Allow jail autocomplete --- usr/local/share/bastille/console.sh | 76 ++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/usr/local/share/bastille/console.sh b/usr/local/share/bastille/console.sh index b15865cc..9e267981 100644 --- a/usr/local/share/bastille/console.sh +++ b/usr/local/share/bastille/console.sh @@ -32,26 +32,60 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille console TARGET [user]" + error_notify "Usage: bastille console [option(s)] TARGET [user]" + cat << EOF + Options: + + -f | --force Start the jail if it is stopped. + -x | --debug Enable debug mode. + +EOF + exit 1 } -# Handle special-case commands first. -case "$1" in -help|-h|--help) - usage - ;; -esac +# Handle options. +FORCE=0 +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -f|--force) + FORCE=1 + shift + ;; + -x|--debug) + enable_debug + shift + ;; + -*) + error_notify "Unknown Option: \"${1}\"" + usage + ;; + *) + break + ;; + esac +done -if [ $# -gt 1 ]; then +if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then usage fi -bastille_root_check +TARGET="${1}" +USER="${2}" -USER="${1}" +bastille_root_check +set_target_single "${TARGET}" +check_target_is_running "${TARGET}" || if [ "${FORCE}" -eq 1 ]; then + bastille start "${TARGET}" +else + error_notify "Jail is not running." + error_exit "Use [-f|--force] to force start the jail." +fi validate_user() { - if jexec -l "${_jail}" id "${USER}" >/dev/null 2>&1; then + if jexec -l "${TARGET}" id "${USER}" >/dev/null 2>&1; then USER_SHELL="$(jexec -l "${_jail}" getent passwd "${USER}" | cut -d: -f7)" if [ -n "${USER_SHELL}" ]; then if jexec -l "${_jail}" grep -qwF "${USER_SHELL}" /etc/shells; then @@ -76,15 +110,11 @@ check_fib() { fi } -for _jail in ${JAILS}; do - info "[${_jail}]:" - LOGIN="$(jexec -l "${_jail}" which login)" - if [ -n "${USER}" ]; then - validate_user - else - check_fib - LOGIN="$(jexec -l "${_jail}" which login)" - ${_setfib} jexec -l "${_jail}" $LOGIN -f root - fi - echo -done +info "[${TARGET}]:" +LOGIN="$(jexec -l "${TARGET}" which login)" +if [ -n "${USER}" ]; then + validate_user +else + LOGIN="$(jexec -l "${TARGET}" which login)" + ${_setfib} jexec -l "${TARGET}" $LOGIN -f root +fi From 61788cce6bf78142d92c6401b32d536b77d37d44 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 5 Jan 2025 19:51:03 -0700 Subject: [PATCH 005/141] fix shellcheck --- usr/local/share/bastille/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index bb3782d6..eae0c506 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -175,7 +175,7 @@ set_target_single() { local _status=0 if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then error_exit "[all|ALL] not supported with this command." - elif echo "${_TARGET}" > /dev/null | grep -Eq '^[0-9]+$'; then + elif echo "${_TARGET}" | grep -Eq '^[0-9]+$'; then if get_jail_name "${_TARGET}" > /dev/null; then _TARGET="$(get_jail_name ${_TARGET})" else From 53295ba69c03a1184de864d7d39e9454296dc21a Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 5 Jan 2025 20:10:37 -0700 Subject: [PATCH 006/141] quick oopsy fix for exporting TARGET --- usr/local/share/bastille/common.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index eae0c506..4778d9ab 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -190,12 +190,11 @@ set_target_single() { else exit 1 fi - else - TARGET="${_TARGET}" - JAILS="${_TARGET}" - export TARGET - export JAILS fi + TARGET="${_TARGET}" + JAILS="${_TARGET}" + export TARGET + export JAILS } target_all_jails() { From f766f26c62376a2f5da050227e28a76a3ce7f27c Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 5 Jan 2025 20:15:01 -0700 Subject: [PATCH 007/141] common: move export to after for loop --- usr/local/share/bastille/common.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 4778d9ab..f48f5c88 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -164,9 +164,9 @@ set_target() { fi TARGET="${TARGET} ${_jail}" JAILS="${JAILS} ${_jail}" - export TARGET - export JAILS done + export TARGET + export JAILS fi } From 02396f569f81dd9f71b32eb7863335caf3a9b78c Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 5 Jan 2025 21:55:28 -0700 Subject: [PATCH 008/141] vnet: start VNET jails at 1 because bastille0 is used as a loopback --- usr/local/share/bastille/common.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index f48f5c88..35d46126 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -230,8 +230,8 @@ generate_vnet_jail_netblock() { ## determine number of interfaces + 1 ## iterate num and grep all jail configs ## define uniq_epair - local _epair_if_count="$(grep -Eos 'epair[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" - local _vnet_if_count="$(grep -Eos 'bastille[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local _epair_if_count="$(grep -Eos 'epair[1-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local _vnet_if_count="$(grep -Eos 'bastille[1-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" local epair_num_range=$((_epair_if_count + 1)) local vnet_num_range=$((_vnet_if_count + 1)) if [ -n "${use_unique_bridge}" ]; then @@ -243,7 +243,7 @@ generate_vnet_jail_netblock() { fi done else - local uniq_epair_bridge="0" + local uniq_epair_bridge="1" fi else if [ "${_vnet_if_count}" -gt 0 ]; then @@ -254,7 +254,7 @@ generate_vnet_jail_netblock() { fi done else - local uniq_epair="bastille0" + local uniq_epair="bastille1" fi fi ## If BRIDGE is enabled, generate bridge config, else generate VNET config From b7ac062a70e034aaa5671fc72dfde55beb370430 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 5 Jan 2025 21:59:12 -0700 Subject: [PATCH 009/141] etcupdate: fix ! --- usr/local/share/bastille/etcupdate.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index ec805726..60634b7b 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -44,7 +44,7 @@ EOF bootstrap_etc_release() { local _release="${1}" local _current="$(sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives | awk -F': ' '{print $2}')" - if ! ls -A "${bastille_releasesdir}/${_release}/usr/src" 2>/dev/null; then + if ls -A "${bastille_releasesdir}/${_release}/usr/src" 2>/dev/null; then sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives=src if ! bastille bootstrap "${_release}"; then error_notify "Failed to bootstrap etcupdate \"${_release}\"" From 50c5e8c4ae8b6e972b4980857fc446129b6e2e5e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 5 Jan 2025 22:06:36 -0700 Subject: [PATCH 010/141] etcupdate: add notice for building tarball --- usr/local/share/bastille/etcupdate.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index 60634b7b..aaded241 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -56,6 +56,7 @@ bootstrap_etc_release() { bootstrap_etc_tarball() { local _release="${1}" if [ ! -f ${bastille_cachedir}/${_release}.tbz2 ]; then + echo "Building tarball, please wait..." if ! etcupdate build -d /tmp/etcupdate -s ${bastille_releasesdir}/${_release}/usr/src ${bastille_cachedir}/${_release}.tbz2; then error_exit "Failed to build etcupdate tarball \"${_release}.tbz2\"" else From 677540aefa02541950b6d6f656edd106f25b71a0 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 6 Jan 2025 08:11:16 -0700 Subject: [PATCH 011/141] clone: change interfaces to start with 1 for VNET This is because bastille0 is always used ad the default loopback when using "bastille setup" and interferes when trying to create the first VNET jail on the list. This ensures that VNET jails will have their epairs (non-bridge) start with bastille1 then 2 then 3 etc... --- usr/local/share/bastille/clone.sh | 104 ++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 35 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index e11bd701..66420860 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -103,47 +103,81 @@ update_jailconf() { update_jailconf_vnet() { bastille_jail_rc_conf="${bastille_jailsdir}/${NEWNAME}/root/etc/rc.conf" - - # Determine number of containers and define an uniq_epair - local list_jails_num="$(bastille list jails | wc -l | awk '{print $1}')" - local num_range="$(expr "${list_jails_num}" + 1)" - jail_list=$(bastille list jail) - for _num in $(seq 0 "${num_range}"); do - if [ -n "${jail_list}" ]; then - if ! grep -q "e0b_bastille${_num}" "${bastille_jailsdir}"/*/jail.conf; then - if ! grep -q "epair${_num}" "${bastille_jailsdir}"/*/jail.conf; then - local uniq_epair="bastille${_num}" + # Determine number of interfaces and define a uniq_epair + local _if_list="$(grep -Eo 'epair[1-9]+|bastille[1-9]+' ${JAIL_CONFIG} | sort -u)" + for _if in ${_if_list}; do + local _epair_if_count="$(grep -Eo 'epair[1-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local _bastille_if_count="$(grep -Eo 'bastille[1-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local epair_num_range=$((_epair_if_count + 1)) + local bastille_num_range=$((_vnet_if_count + 1)) + if echo ${_if} | grep -Eoq 'epair[1-9]+'; then + # Update bridged VNET config + for _num in $(seq 0 "${epair_num_range}"); do + if ! grep -Eoq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then + # Update jail.conf epair name local uniq_epair_bridge="${_num}" - # since we don't have access to the external_interface variable, we cat the jail.conf file to retrieve the mac prefix + local _if_epaira="$(grep "${_if}" ${JAIL_CONFIG} | grep -Eo -m 1 "epair[1-9]+a")" + local _if_epairb="$(grep "${_if}" ${JAIL_CONFIG} | grep -Eo -m 1 "epair[1-9]+b")" + local _if_vnet="$(grep ${_if_epairb} "${bastille_jail_rc_conf}" | grep -Eo -m 1 "vnet[1-9]+")" + sed -i '' "s|${_if}|epair${uniq_epair_bridge}|g" "${JAIL_CONFIG}" + # since we don't have access to the external_interface variable, we cat the jail.conf file to retrieve the mac prefix # we also do not use the main generate_static_mac function here - local macaddr_prefix="$(cat ${JAIL_CONFIG} | grep -m 1 ether | grep -oE '([0-9a-f]{2}(:[0-9a-f]{2}){5})' | awk -F: '{print $1":"$2":"$3}')" - local macaddr_suffix="$(echo -n ${NEWNAME} | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" - local macaddr="${macaddr_prefix}:${macaddr_suffix}" - # Update the exec.* with uniq_epair when cloning jails. - # for VNET jails - sed -i '' "s|bastille\([0-9]\{1,\}\)|${uniq_epair}|g" "${JAIL_CONFIG}" - sed -i '' "s|e\([0-9]\{1,\}\)a_${NEWNAME}|e${uniq_epair_bridge}a_${NEWNAME}|g" "${JAIL_CONFIG}" - sed -i '' "s|e\([0-9]\{1,\}\)b_${NEWNAME}|e${uniq_epair_bridge}b_${NEWNAME}|g" "${JAIL_CONFIG}" - sed -i '' "s|epair\([0-9]\{1,\}\)|epair${uniq_epair_bridge}|g" "${JAIL_CONFIG}" - sed -i '' "s|exec.prestart += \"ifconfig e0a_bastille\([0-9]\{1,\}\).*description.*|exec.prestart += \"ifconfig e0a_${uniq_epair} description \\\\\"vnet host interface for Bastille jail ${NEWNAME}\\\\\"\";|" "${JAIL_CONFIG}" - sed -i '' "s|ether.*:.*:.*:.*:.*:.*a\";|ether ${macaddr}a\";|" "${JAIL_CONFIG}" - sed -i '' "s|ether.*:.*:.*:.*:.*:.*b\";|ether ${macaddr}b\";|" "${JAIL_CONFIG}" + if grep -Eo "${_if}" ${JAIL_CONFIG} | grep -oq ether; then + local macaddr_prefix="$(cat ${JAIL_CONFIG} | grep ${_if} | grep -m 1 ether | grep -oE '([0-9a-f]{2}(:[0-9a-f]{2}){5})' | awk -F: '{print $1":"$2":"$3}')" + local macaddr_suffix="$(echo -n ${NEWNAME} | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" + local macaddr="${macaddr_prefix}:${macaddr_suffix}" + sed -i '' "s|epair${uniq_epair}a ether.*:.*:.*:.*:.*:.*a\";|epair${uniq_epair}a ether ${macaddr}a\";|" "${JAIL_CONFIG}" + sed -i '' "s|epair${uniq_epair}b ether.*:.*:.*:.*:.*:.*b\";|epair${uniq_epair}b ether ${macaddr}b\";|" "${JAIL_CONFIG}" + fi + sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${JAIL_CONFIG}" + # Update /etc/rc.conf + sed -i '' "s|${_if_epairb}_name|epair${uniq_epair_bridge}b_name|" "${bastille_jail_rc_conf}" + if grep "vnet0" "${bastille_jail_rc_conf}" | grep -q "epair${uniq_epair_bridge}b_name"; then + if [ "${IP}" = "0.0.0.0" ]; then + sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="SYNCDHCP" + else + sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="inet ${IP}" + fi + else + sysrc -f "${bastille_jail_rc_conf}" ifconfig_${_if_vnet}="SYNCDHCP" + fi break fi - fi + done + elif echo ${_if} | grep -Eoq 'bastille[0-9]+'; then + # Update VNET config + for _num in $(seq 0 "${bastille_num_range}"); do + if ! grep -Eoq "bastille${_num}" ${bastille_jailsdir}/*/jail.conf; then + # Update jail.conf epair name + local uniq_epair="bastille${_num}" + local _if_vnet="$(grep ${_if} "${bastille_jail_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" + sed -i '' "s|${_if}|${uniq_epair}|g" "${JAIL_CONFIG}" + # since we don't have access to the external_interface variable, we cat the jail.conf file to retrieve the mac prefix + # we also do not use the main generate_static_mac function here + if grep -Eo ${_if} ${JAIL_CONFIG} | grep -oq ether; then + local macaddr_prefix="$(cat ${JAIL_CONFIG} | grep ${_if} | grep -m 1 ether | grep -oE '([0-9a-f]{2}(:[0-9a-f]{2}){5})' | awk -F: '{print $1":"$2":"$3}')" + local macaddr_suffix="$(echo -n ${NEWNAME} | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" + local macaddr="${macaddr_prefix}:${macaddr_suffix}" + sed -i '' "s|${uniq_epair} ether.*:.*:.*:.*:.*:.*a\";|${uniq_epair} ether ${macaddr}a\";|" "${JAIL_CONFIG}" + sed -i '' "s|${uniq_epair} ether.*:.*:.*:.*:.*:.*b\";|${uniq_epair} ether ${macaddr}b\";|" "${JAIL_CONFIG}" + fi + sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${JAIL_CONFIG}" + # Update /etc/rc.conf + sed -i '' "s|ifconfig_e0b_${_if}_name|ifconfig_e0b_${uniq_epair}_name|" "${bastille_jail_rc_conf}" + if grep "vnet0" "${bastille_jail_rc_conf}" | grep -q ${uniq_epair}; then + if [ "${IP}" = "0.0.0.0" ]; then + sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="SYNCDHCP" + else + sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0=" inet ${IP} " + fi + else + sysrc -f "${bastille_jail_rc_conf}" ifconfig_${_if_vnet}="SYNCDHCP" + fi + break + fi + done fi done - - # Rename interface to new uniq_epair - sed -i '' "s|ifconfig_e0b_bastille.*_name|ifconfig_e0b_${uniq_epair}_name|" "${bastille_jail_rc_conf}" - sed -i '' "s|ifconfig_e.*b_${TARGET}_name|ifconfig_e${uniq_epair_bridge}b_${NEWNAME}_name|" "${bastille_jail_rc_conf}" - - # If 0.0.0.0 set DHCP, else set static IP address - if [ "${IP}" = "0.0.0.0" ]; then - sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="SYNCDHCP" - else - sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="inet ${IP}" - fi } update_fstab() { From 0c2c93c1098a6c1345371c9c71000f8ecf85a5a8 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 6 Jan 2025 08:12:47 -0700 Subject: [PATCH 012/141] clone: quietly check for "ether" string when cloning --- usr/local/share/bastille/clone.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index 66420860..3980c09a 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -122,7 +122,7 @@ update_jailconf_vnet() { sed -i '' "s|${_if}|epair${uniq_epair_bridge}|g" "${JAIL_CONFIG}" # since we don't have access to the external_interface variable, we cat the jail.conf file to retrieve the mac prefix # we also do not use the main generate_static_mac function here - if grep -Eo "${_if}" ${JAIL_CONFIG} | grep -oq ether; then + if grep -oq "${_if}" ${JAIL_CONFIG} | grep -oq ether; then local macaddr_prefix="$(cat ${JAIL_CONFIG} | grep ${_if} | grep -m 1 ether | grep -oE '([0-9a-f]{2}(:[0-9a-f]{2}){5})' | awk -F: '{print $1":"$2":"$3}')" local macaddr_suffix="$(echo -n ${NEWNAME} | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" local macaddr="${macaddr_prefix}:${macaddr_suffix}" @@ -154,7 +154,7 @@ update_jailconf_vnet() { sed -i '' "s|${_if}|${uniq_epair}|g" "${JAIL_CONFIG}" # since we don't have access to the external_interface variable, we cat the jail.conf file to retrieve the mac prefix # we also do not use the main generate_static_mac function here - if grep -Eo ${_if} ${JAIL_CONFIG} | grep -oq ether; then + if grep -oq ${_if} ${JAIL_CONFIG} | grep -oq ether; then local macaddr_prefix="$(cat ${JAIL_CONFIG} | grep ${_if} | grep -m 1 ether | grep -oE '([0-9a-f]{2}(:[0-9a-f]{2}){5})' | awk -F: '{print $1":"$2":"$3}')" local macaddr_suffix="$(echo -n ${NEWNAME} | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" local macaddr="${macaddr_prefix}:${macaddr_suffix}" From 49a9ce99132e481307c4a5dc704e2883d9831967 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 6 Jan 2025 08:54:47 -0700 Subject: [PATCH 013/141] clone: 0>1 for base interface grep --- usr/local/share/bastille/clone.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index 3980c09a..5bf85b3b 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -42,7 +42,7 @@ help|-h|--help) ;; esac -if [ $# -ne 2 ]; then +if [ "$#" -ne 2 ]; then usage fi @@ -112,8 +112,8 @@ update_jailconf_vnet() { local bastille_num_range=$((_vnet_if_count + 1)) if echo ${_if} | grep -Eoq 'epair[1-9]+'; then # Update bridged VNET config - for _num in $(seq 0 "${epair_num_range}"); do - if ! grep -Eoq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then + for _num in $(seq 1 "${epair_num_range}"); do + if ! grep -oq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then # Update jail.conf epair name local uniq_epair_bridge="${_num}" local _if_epaira="$(grep "${_if}" ${JAIL_CONFIG} | grep -Eo -m 1 "epair[1-9]+a")" @@ -144,10 +144,10 @@ update_jailconf_vnet() { break fi done - elif echo ${_if} | grep -Eoq 'bastille[0-9]+'; then + elif echo ${_if} | grep -Eoq 'bastille[1-9]+'; then # Update VNET config - for _num in $(seq 0 "${bastille_num_range}"); do - if ! grep -Eoq "bastille${_num}" ${bastille_jailsdir}/*/jail.conf; then + for _num in $(seq 1 "${bastille_num_range}"); do + if ! grep -oq "bastille${_num}" ${bastille_jailsdir}/*/jail.conf; then # Update jail.conf epair name local uniq_epair="bastille${_num}" local _if_vnet="$(grep ${_if} "${bastille_jail_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" From 873a5230c4046804f6aee54a5c31f2beade2d1b6 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 6 Jan 2025 08:57:00 -0700 Subject: [PATCH 014/141] common: 0>1 for base interface grep --- usr/local/share/bastille/common.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 35d46126..f2c3b6a3 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -236,8 +236,8 @@ generate_vnet_jail_netblock() { local vnet_num_range=$((_vnet_if_count + 1)) if [ -n "${use_unique_bridge}" ]; then if [ "${_epair_if_count}" -gt 0 ]; then - for _num in $(seq 0 "${epair_num_range}"); do - if ! grep -Eosq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then + for _num in $(seq 1 "${epair_num_range}"); do + if ! grep -osq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then local uniq_epair_bridge="${_num}" break fi @@ -247,8 +247,8 @@ generate_vnet_jail_netblock() { fi else if [ "${_vnet_if_count}" -gt 0 ]; then - for _num in $(seq 0 "${vnet_num_range}"); do - if ! grep -Eosq "bastillle${_num}" ${bastille_jailsdir}/*/jail.conf; then + for _num in $(seq 1 "${vnet_num_range}"); do + if ! grep -osq "bastillle${_num}" ${bastille_jailsdir}/*/jail.conf; then local uniq_epair="bastille${_num}" break fi From e9ad74d0008e9abb7be391a234e772425ab14af4 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:40:18 -0700 Subject: [PATCH 015/141] clone: revert VNET function --- usr/local/share/bastille/clone.sh | 106 ++++++++++-------------------- 1 file changed, 36 insertions(+), 70 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index 5bf85b3b..e11bd701 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -42,7 +42,7 @@ help|-h|--help) ;; esac -if [ "$#" -ne 2 ]; then +if [ $# -ne 2 ]; then usage fi @@ -103,81 +103,47 @@ update_jailconf() { update_jailconf_vnet() { bastille_jail_rc_conf="${bastille_jailsdir}/${NEWNAME}/root/etc/rc.conf" - # Determine number of interfaces and define a uniq_epair - local _if_list="$(grep -Eo 'epair[1-9]+|bastille[1-9]+' ${JAIL_CONFIG} | sort -u)" - for _if in ${_if_list}; do - local _epair_if_count="$(grep -Eo 'epair[1-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" - local _bastille_if_count="$(grep -Eo 'bastille[1-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" - local epair_num_range=$((_epair_if_count + 1)) - local bastille_num_range=$((_vnet_if_count + 1)) - if echo ${_if} | grep -Eoq 'epair[1-9]+'; then - # Update bridged VNET config - for _num in $(seq 1 "${epair_num_range}"); do - if ! grep -oq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then - # Update jail.conf epair name - local uniq_epair_bridge="${_num}" - local _if_epaira="$(grep "${_if}" ${JAIL_CONFIG} | grep -Eo -m 1 "epair[1-9]+a")" - local _if_epairb="$(grep "${_if}" ${JAIL_CONFIG} | grep -Eo -m 1 "epair[1-9]+b")" - local _if_vnet="$(grep ${_if_epairb} "${bastille_jail_rc_conf}" | grep -Eo -m 1 "vnet[1-9]+")" - sed -i '' "s|${_if}|epair${uniq_epair_bridge}|g" "${JAIL_CONFIG}" - # since we don't have access to the external_interface variable, we cat the jail.conf file to retrieve the mac prefix - # we also do not use the main generate_static_mac function here - if grep -oq "${_if}" ${JAIL_CONFIG} | grep -oq ether; then - local macaddr_prefix="$(cat ${JAIL_CONFIG} | grep ${_if} | grep -m 1 ether | grep -oE '([0-9a-f]{2}(:[0-9a-f]{2}){5})' | awk -F: '{print $1":"$2":"$3}')" - local macaddr_suffix="$(echo -n ${NEWNAME} | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" - local macaddr="${macaddr_prefix}:${macaddr_suffix}" - sed -i '' "s|epair${uniq_epair}a ether.*:.*:.*:.*:.*:.*a\";|epair${uniq_epair}a ether ${macaddr}a\";|" "${JAIL_CONFIG}" - sed -i '' "s|epair${uniq_epair}b ether.*:.*:.*:.*:.*:.*b\";|epair${uniq_epair}b ether ${macaddr}b\";|" "${JAIL_CONFIG}" - fi - sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${JAIL_CONFIG}" - # Update /etc/rc.conf - sed -i '' "s|${_if_epairb}_name|epair${uniq_epair_bridge}b_name|" "${bastille_jail_rc_conf}" - if grep "vnet0" "${bastille_jail_rc_conf}" | grep -q "epair${uniq_epair_bridge}b_name"; then - if [ "${IP}" = "0.0.0.0" ]; then - sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="SYNCDHCP" - else - sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="inet ${IP}" - fi - else - sysrc -f "${bastille_jail_rc_conf}" ifconfig_${_if_vnet}="SYNCDHCP" - fi - break - fi - done - elif echo ${_if} | grep -Eoq 'bastille[1-9]+'; then - # Update VNET config - for _num in $(seq 1 "${bastille_num_range}"); do - if ! grep -oq "bastille${_num}" ${bastille_jailsdir}/*/jail.conf; then - # Update jail.conf epair name + + # Determine number of containers and define an uniq_epair + local list_jails_num="$(bastille list jails | wc -l | awk '{print $1}')" + local num_range="$(expr "${list_jails_num}" + 1)" + jail_list=$(bastille list jail) + for _num in $(seq 0 "${num_range}"); do + if [ -n "${jail_list}" ]; then + if ! grep -q "e0b_bastille${_num}" "${bastille_jailsdir}"/*/jail.conf; then + if ! grep -q "epair${_num}" "${bastille_jailsdir}"/*/jail.conf; then local uniq_epair="bastille${_num}" - local _if_vnet="$(grep ${_if} "${bastille_jail_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" - sed -i '' "s|${_if}|${uniq_epair}|g" "${JAIL_CONFIG}" - # since we don't have access to the external_interface variable, we cat the jail.conf file to retrieve the mac prefix + local uniq_epair_bridge="${_num}" + # since we don't have access to the external_interface variable, we cat the jail.conf file to retrieve the mac prefix # we also do not use the main generate_static_mac function here - if grep -oq ${_if} ${JAIL_CONFIG} | grep -oq ether; then - local macaddr_prefix="$(cat ${JAIL_CONFIG} | grep ${_if} | grep -m 1 ether | grep -oE '([0-9a-f]{2}(:[0-9a-f]{2}){5})' | awk -F: '{print $1":"$2":"$3}')" - local macaddr_suffix="$(echo -n ${NEWNAME} | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" - local macaddr="${macaddr_prefix}:${macaddr_suffix}" - sed -i '' "s|${uniq_epair} ether.*:.*:.*:.*:.*:.*a\";|${uniq_epair} ether ${macaddr}a\";|" "${JAIL_CONFIG}" - sed -i '' "s|${uniq_epair} ether.*:.*:.*:.*:.*:.*b\";|${uniq_epair} ether ${macaddr}b\";|" "${JAIL_CONFIG}" - fi - sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${JAIL_CONFIG}" - # Update /etc/rc.conf - sed -i '' "s|ifconfig_e0b_${_if}_name|ifconfig_e0b_${uniq_epair}_name|" "${bastille_jail_rc_conf}" - if grep "vnet0" "${bastille_jail_rc_conf}" | grep -q ${uniq_epair}; then - if [ "${IP}" = "0.0.0.0" ]; then - sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="SYNCDHCP" - else - sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0=" inet ${IP} " - fi - else - sysrc -f "${bastille_jail_rc_conf}" ifconfig_${_if_vnet}="SYNCDHCP" - fi + local macaddr_prefix="$(cat ${JAIL_CONFIG} | grep -m 1 ether | grep -oE '([0-9a-f]{2}(:[0-9a-f]{2}){5})' | awk -F: '{print $1":"$2":"$3}')" + local macaddr_suffix="$(echo -n ${NEWNAME} | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" + local macaddr="${macaddr_prefix}:${macaddr_suffix}" + # Update the exec.* with uniq_epair when cloning jails. + # for VNET jails + sed -i '' "s|bastille\([0-9]\{1,\}\)|${uniq_epair}|g" "${JAIL_CONFIG}" + sed -i '' "s|e\([0-9]\{1,\}\)a_${NEWNAME}|e${uniq_epair_bridge}a_${NEWNAME}|g" "${JAIL_CONFIG}" + sed -i '' "s|e\([0-9]\{1,\}\)b_${NEWNAME}|e${uniq_epair_bridge}b_${NEWNAME}|g" "${JAIL_CONFIG}" + sed -i '' "s|epair\([0-9]\{1,\}\)|epair${uniq_epair_bridge}|g" "${JAIL_CONFIG}" + sed -i '' "s|exec.prestart += \"ifconfig e0a_bastille\([0-9]\{1,\}\).*description.*|exec.prestart += \"ifconfig e0a_${uniq_epair} description \\\\\"vnet host interface for Bastille jail ${NEWNAME}\\\\\"\";|" "${JAIL_CONFIG}" + sed -i '' "s|ether.*:.*:.*:.*:.*:.*a\";|ether ${macaddr}a\";|" "${JAIL_CONFIG}" + sed -i '' "s|ether.*:.*:.*:.*:.*:.*b\";|ether ${macaddr}b\";|" "${JAIL_CONFIG}" break fi - done + fi fi done + + # Rename interface to new uniq_epair + sed -i '' "s|ifconfig_e0b_bastille.*_name|ifconfig_e0b_${uniq_epair}_name|" "${bastille_jail_rc_conf}" + sed -i '' "s|ifconfig_e.*b_${TARGET}_name|ifconfig_e${uniq_epair_bridge}b_${NEWNAME}_name|" "${bastille_jail_rc_conf}" + + # If 0.0.0.0 set DHCP, else set static IP address + if [ "${IP}" = "0.0.0.0" ]; then + sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="SYNCDHCP" + else + sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="inet ${IP}" + fi } update_fstab() { From a9bd2d55c1212b58f1d5ca5352028fb48cf577d4 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:41:30 -0700 Subject: [PATCH 016/141] common.sh: revert VNET function --- usr/local/share/bastille/common.sh | 93 +++++++++--------------------- 1 file changed, 28 insertions(+), 65 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index f2c3b6a3..d02d3ab1 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -222,74 +222,47 @@ generate_static_mac() { } generate_vnet_jail_netblock() { - local jail_name="${1}" - local use_unique_bridge="${2}" - local external_interface="${3}" - # setting this to 1 temprarily until we integrate the -M switch - local static_mac=1 - ## determine number of interfaces + 1 + local jail_name="$1" + local use_unique_bridge="$2" + local external_interface="$3" + generate_static_mac "${jail_name}" "${external_interface}" + ## determine number of containers + 1 ## iterate num and grep all jail configs ## define uniq_epair - local _epair_if_count="$(grep -Eos 'epair[1-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" - local _vnet_if_count="$(grep -Eos 'bastille[1-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" - local epair_num_range=$((_epair_if_count + 1)) - local vnet_num_range=$((_vnet_if_count + 1)) - if [ -n "${use_unique_bridge}" ]; then - if [ "${_epair_if_count}" -gt 0 ]; then - for _num in $(seq 1 "${epair_num_range}"); do - if ! grep -osq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then + local jail_list="$(bastille list jails)" + if [ -n "${jail_list}" ]; then + local list_jails_num="$(echo "${jail_list}" | wc -l | awk '{print $1}')" + local num_range=$((list_jails_num + 1)) + for _num in $(seq 0 "${num_range}"); do + if ! grep -q "e[0-9]b_bastille${_num}" "${bastille_jailsdir}"/*/jail.conf; then + if ! grep -q "epair${_num}" "${bastille_jailsdir}"/*/jail.conf; then + local uniq_epair="bastille${_num}" local uniq_epair_bridge="${_num}" break fi - done - else - local uniq_epair_bridge="1" - fi + fi + done else - if [ "${_vnet_if_count}" -gt 0 ]; then - for _num in $(seq 1 "${vnet_num_range}"); do - if ! grep -osq "bastillle${_num}" ${bastille_jailsdir}/*/jail.conf; then - local uniq_epair="bastille${_num}" - break - fi - done - else - local uniq_epair="bastille1" - fi + local uniq_epair="bastille0" + local uniq_epair_bridge="0" fi - ## If BRIDGE is enabled, generate bridge config, else generate VNET config if [ -n "${use_unique_bridge}" ]; then - if [ -n "${static_mac}" ]; then - ## Generate bridged VNET config with static MAC address - generate_static_mac "${jail_name}" "${external_interface}" - cat <<-EOF + ## generate bridge config + cat <<-EOF vnet; - vnet.interface = epair${uniq_epair_bridge}b; + vnet.interface = e${uniq_epair_bridge}b_${jail_name}; exec.prestart += "ifconfig epair${uniq_epair_bridge} create"; exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}a ether ${macaddr}a"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}b ether ${macaddr}b"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}a description \"vnet host interface for Bastille jail ${jail_name}\""; - exec.poststop += "ifconfig ${external_interface} deletem epair${uniq_epair_bridge}a"; - exec.poststop += "ifconfig epair${uniq_epair_bridge}a destroy"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}a up name e${uniq_epair_bridge}a_${jail_name}"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}b up name e${uniq_epair_bridge}b_${jail_name}"; + exec.prestart += "ifconfig e${uniq_epair_bridge}a_${jail_name} ether ${macaddr}a"; + exec.prestart += "ifconfig e${uniq_epair_bridge}b_${jail_name} ether ${macaddr}b"; + exec.poststop += "ifconfig ${external_interface} deletem e${uniq_epair_bridge}a_${jail_name}"; + exec.poststop += "ifconfig e${uniq_epair_bridge}a_${jail_name} destroy"; EOF - else - ## Generate bridged VNET config without static MAC address - cat <<-EOF - vnet; - vnet.interface = epair${uniq_epair_bridge}b; - exec.prestart += "ifconfig epair${uniq_epair_bridge} create"; - exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}a description \"vnet host interface for Bastille jail ${jail_name}\""; - exec.poststop += "ifconfig ${external_interface} deletem epair${uniq_epair_bridge}a"; - exec.poststop += "ifconfig epair${uniq_epair_bridge}a destroy"; -EOF - fi else - if [ -n "${static_mac}" ]; then - ## Generate VNET config with static MAC address - generate_static_mac "${jail_name}" "${external_interface}" - cat <<-EOF + ## generate config + cat <<-EOF vnet; vnet.interface = e0b_${uniq_epair}; exec.prestart += "jib addm ${uniq_epair} ${external_interface}"; @@ -298,16 +271,6 @@ EOF exec.prestart += "ifconfig e0a_${uniq_epair} description \"vnet host interface for Bastille jail ${jail_name}\""; exec.poststop += "jib destroy ${uniq_epair}"; EOF - else - ## Generate VNET config without static MAC address - cat <<-EOF - vnet; - vnet.interface = e0b_${uniq_epair}; - exec.prestart += "jib addm ${uniq_epair} ${external_interface}"; - exec.prestart += "ifconfig e0a_${uniq_epair} description \"vnet host interface for Bastille jail ${jail_name}\""; - exec.poststop += "jib destroy ${uniq_epair}"; -EOF - fi fi } From 5d3f4732fb966993f87b59a39dc8f185780736f4 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:45:44 -0700 Subject: [PATCH 017/141] common: grep quietly for "check_target_is*" functions --- usr/local/share/bastille/common.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index d02d3ab1..82ac3418 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -88,7 +88,7 @@ warn() { check_target_exists() { local _TARGET="${1}" local _jaillist="$(bastille list jails)" - if ! echo "${_jaillist}" | grep -Eq "^${_TARGET}$"; then + if ! echo "${_jaillist}" | grep -Eoq "^${_TARGET}$"; then return 1 else return 0 @@ -97,7 +97,7 @@ check_target_exists() { check_target_is_running() { local _TARGET="${1}" - if ! jls name | grep -Eq "^${_TARGET}$"; then + if ! jls name | grep -Eoq "^${_TARGET}$"; then return 1 else return 0 @@ -106,7 +106,7 @@ check_target_is_running() { check_target_is_stopped() { local _TARGET="${1}" - if jls name | grep -Eq "^${_TARGET}$"; then + if jls name | grep -Eoq "^${_TARGET}$"; then return 1 else return 0 From 27fe77d5f9a369b83dd641442255d321ed431fbd Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 6 Jan 2025 17:33:29 -0700 Subject: [PATCH 018/141] console: use -s to force start instead of -f This is because -f typically is used to force and option. Example being in destroy.sh I think it more consistent to use -s to auto start/stop a jail it the script requires it. --- usr/local/share/bastille/console.sh | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/usr/local/share/bastille/console.sh b/usr/local/share/bastille/console.sh index 9e267981..1afd059e 100644 --- a/usr/local/share/bastille/console.sh +++ b/usr/local/share/bastille/console.sh @@ -36,7 +36,7 @@ usage() { cat << EOF Options: - -f | --force Start the jail if it is stopped. + -s | --start Start the jail if it is stopped. -x | --debug Enable debug mode. EOF @@ -44,14 +44,14 @@ EOF } # Handle options. -FORCE=0 +START=0 while [ "$#" -gt 0 ]; do case "${1}" in -h|--help|help) usage ;; - -f|--force) - FORCE=1 + -s|--start) + START=1 shift ;; -x|--debug) @@ -59,8 +59,14 @@ while [ "$#" -gt 0 ]; do shift ;; -*) - error_notify "Unknown Option: \"${1}\"" - usage + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + x) enable_debug ;; + s) START=1 ;; + *) error_exit "Unknown Option: \"${1}\"" ;; + esac + done + shift ;; *) break @@ -77,11 +83,11 @@ USER="${2}" bastille_root_check set_target_single "${TARGET}" -check_target_is_running "${TARGET}" || if [ "${FORCE}" -eq 1 ]; then +check_target_is_running "${TARGET}" || if [ "${START}" -eq 1 ]; then bastille start "${TARGET}" else error_notify "Jail is not running." - error_exit "Use [-f|--force] to force start the jail." + error_exit "Use [-s|--start] to force start the jail." fi validate_user() { From e3a57e21eaa4e4f7f9c4856b35caf297a5a11b1f Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:42:44 -0700 Subject: [PATCH 019/141] common: simplify debug message --- usr/local/share/bastille/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 82ac3418..a26de72f 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -49,7 +49,7 @@ enable_color() { enable_debug() { # Enable debug mode. - warn "***DEBUG MODE START***" + warn "***DEBUG MODE***" set -x } From 0aac59ae5ab046ecdf2aae9f6135b7a4c4cf5821 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:44:48 -0700 Subject: [PATCH 020/141] console: Change -s to -a --- usr/local/share/bastille/console.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/usr/local/share/bastille/console.sh b/usr/local/share/bastille/console.sh index 1afd059e..1918fe4c 100644 --- a/usr/local/share/bastille/console.sh +++ b/usr/local/share/bastille/console.sh @@ -36,7 +36,7 @@ usage() { cat << EOF Options: - -s | --start Start the jail if it is stopped. + -a | --auto Auto mode. Start/stop jail if required. -x | --debug Enable debug mode. EOF @@ -44,14 +44,14 @@ EOF } # Handle options. -START=0 +AUTO=0 while [ "$#" -gt 0 ]; do case "${1}" in -h|--help|help) usage ;; - -s|--start) - START=1 + -a|--auto) + AUTO=1 shift ;; -x|--debug) @@ -62,7 +62,7 @@ while [ "$#" -gt 0 ]; do for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do case ${_opt} in x) enable_debug ;; - s) START=1 ;; + a) AUTO=1 ;; *) error_exit "Unknown Option: \"${1}\"" ;; esac done @@ -83,11 +83,11 @@ USER="${2}" bastille_root_check set_target_single "${TARGET}" -check_target_is_running "${TARGET}" || if [ "${START}" -eq 1 ]; then +check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then bastille start "${TARGET}" else error_notify "Jail is not running." - error_exit "Use [-s|--start] to force start the jail." + error_exit "Use [-a|--auto] to auto-start the jail." fi validate_user() { From 0d09ac9607816613b6e8ad20c3410adae814b105 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 7 Jan 2025 17:14:02 -0700 Subject: [PATCH 021/141] etcupdate: error when RELEASE not bootstrapped --- usr/local/share/bastille/etcupdate.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index aaded241..4878e8b0 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -47,9 +47,11 @@ bootstrap_etc_release() { if ls -A "${bastille_releasesdir}/${_release}/usr/src" 2>/dev/null; then sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives=src if ! bastille bootstrap "${_release}"; then - error_notify "Failed to bootstrap etcupdate \"${_release}\"" + sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}" + error_exit "Failed to bootstrap etcupdate \"${_release}\"" + else + sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}" fi - sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}" fi } @@ -71,6 +73,9 @@ bootstrap_etc_tarball() { update_jail_etc() { local _jail="${1}" local _release="${2}" + if [ ! -f ${bastille_cachedir}/${_release}.tbz2 ]; then + error_exit "Error: Please run \"bastille etcupdate bootstrap RELEASE\" first." + fi if [ "${DRY_RUN}" -eq 1 ]; then info "[_jail]: --dry-run" etcupdate -n -D "${bastille_jailsdir}"/"${_jail}"/root -t ${bastille_cachedir}/${_release}.tbz2 From 18826666d79be0a1357bbb96c152f7634a714929 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 8 Jan 2025 12:59:55 -0700 Subject: [PATCH 022/141] common: support single target function error when multi-target selected --- usr/local/share/bastille/common.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index a26de72f..4e0272b3 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -175,6 +175,8 @@ set_target_single() { local _status=0 if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then error_exit "[all|ALL] not supported with this command." + elif [ "$(echo ${_TARGET} | wc -w)" -gt 1 ]; then + error_exit "Error: Command only supports a single TARGET." elif echo "${_TARGET}" | grep -Eq '^[0-9]+$'; then if get_jail_name "${_TARGET}" > /dev/null; then _TARGET="$(get_jail_name ${_TARGET})" From 3c49a47f49046dfe3db9a19424458001977ddb63 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 9 Jan 2025 09:18:53 -0700 Subject: [PATCH 023/141] console: jail > jail(s) --- usr/local/share/bastille/console.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/console.sh b/usr/local/share/bastille/console.sh index 1918fe4c..ec3a380d 100644 --- a/usr/local/share/bastille/console.sh +++ b/usr/local/share/bastille/console.sh @@ -36,7 +36,7 @@ usage() { cat << EOF Options: - -a | --auto Auto mode. Start/stop jail if required. + -a | --auto Auto mode. Start/stop jail(s) if required. -x | --debug Enable debug mode. EOF From 4aff04d037668066bfcc3d963308a9ae4af6cace Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 9 Jan 2025 09:22:22 -0700 Subject: [PATCH 024/141] console: missed check_fib function --- usr/local/share/bastille/console.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/usr/local/share/bastille/console.sh b/usr/local/share/bastille/console.sh index ec3a380d..c4fcbfd3 100644 --- a/usr/local/share/bastille/console.sh +++ b/usr/local/share/bastille/console.sh @@ -121,6 +121,7 @@ LOGIN="$(jexec -l "${TARGET}" which login)" if [ -n "${USER}" ]; then validate_user else + check_fib LOGIN="$(jexec -l "${TARGET}" which login)" ${_setfib} jexec -l "${TARGET}" $LOGIN -f root fi From 9c79f138e7f3671cf3abfef506dcdac7f0837008 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:37:04 -0700 Subject: [PATCH 025/141] etcupdate: add resolve mode --- usr/local/share/bastille/etcupdate.sh | 101 ++++++++++++++++++-------- 1 file changed, 72 insertions(+), 29 deletions(-) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index 4878e8b0..ed579597 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -31,11 +31,13 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_notify "Usage: bastille etcupdate [option(s)] [TARGET|bootstrap] RELEASE" + error_notify "Usage: bastille etcupdate [option(s)] [bootstrap|TARGET] [update RELEASE|resolve]" cat << EOF Options: -d | --dry-run Show output, but do not apply. + -f | --force Force a re-bootstrap of a RELEASE. + -x | --debug Enable debug mode. EOF exit 1 @@ -47,11 +49,9 @@ bootstrap_etc_release() { if ls -A "${bastille_releasesdir}/${_release}/usr/src" 2>/dev/null; then sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives=src if ! bastille bootstrap "${_release}"; then - sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}" - error_exit "Failed to bootstrap etcupdate \"${_release}\"" - else - sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}" + error_notify "Failed to bootstrap etcupdate: ${_release}" fi + sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}" fi } @@ -62,50 +62,88 @@ bootstrap_etc_tarball() { if ! etcupdate build -d /tmp/etcupdate -s ${bastille_releasesdir}/${_release}/usr/src ${bastille_cachedir}/${_release}.tbz2; then error_exit "Failed to build etcupdate tarball \"${_release}.tbz2\"" else - info "Etcupdate bootstrap complete: \"${_release}\"" + info "Etcupdate bootstrap complete: ${_release}" + fi + elif [ -f ${bastille_cachedir}/${_release}.tbz2 ] && [ "${FORCE}" -eq 1 ]; then + rm -f "${bastille_cachedir}/${_release}.tbz2" + echo "Building tarball, please wait..." + if ! etcupdate build -d /tmp/etcupdate -s ${bastille_releasesdir}/${_release}/usr/src ${bastille_cachedir}/${_release}.tbz2; then + error_exit "Failed to build etcupdate tarball \"${_release}.tbz2\"" + else + info "Etcupdate bootstrap complete: ${_release}" fi else - info "Etcupdate release has already been prepared for application: \"${_release}\"" - exit 0 + info "Etcupdate release has already been prepared for application: ${_release}" fi } +resolve_conflicts() { + local _jail="${1}" + if [ "${DRY_RUN}" -eq 1 ]; then + info "[_jail]: --dry-run" + etcupdate resolve -n -D "${bastille_jailsdir}/${_jail}/root" + else + info "[_jail]:" + etcupdate resolve -D "${bastille_jailsdir}/${_jail}/root" + fi +} + update_jail_etc() { local _jail="${1}" local _release="${2}" - if [ ! -f ${bastille_cachedir}/${_release}.tbz2 ]; then - error_exit "Error: Please run \"bastille etcupdate bootstrap RELEASE\" first." - fi if [ "${DRY_RUN}" -eq 1 ]; then info "[_jail]: --dry-run" - etcupdate -n -D "${bastille_jailsdir}"/"${_jail}"/root -t ${bastille_cachedir}/${_release}.tbz2 + etcupdate -n -D "${bastille_jailsdir}/${_jail}/root" -t ${bastille_cachedir}/${_release}.tbz2 else info "[_jail]:" - etcupdate -D "${bastille_jailsdir}"/"${_jail}"/root -t ${bastille_cachedir}/${_release}.tbz2 + etcupdate -D "${bastille_jailsdir}/${_jail}/root" -t ${bastille_cachedir}/${_release}.tbz2 fi } -if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then +if [ "$#" -lt 2 ] || [ "$#" -gt 4 ]; then usage fi # Handle options. +DRY_RUN=0 +FORCE=0 while [ "$#" -gt 0 ]; do case "${1}" in -h|--help|help) usage ;; -d|--dry-run) - if [ -z "${2}" ] || [ -z "${3}" ]; then - usage - else - DRY_RUN=1 - shift - fi + DRY_RUN=1 + shift ;; - -*) - error_exit "Unknown option: \"${1}\"" + -f|--force) + FORCE=1 + shift ;; + -x|--debug) + enable_debug + shift + ;; + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + d) DRY_RUN=1 ;; + f) FORCE=1 ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" ;; + esac + done + shift + ;; + *) + break + ;; + esac +done + +# Main commands +while [ "$#" -gt 0 ]; do + case "${1}" in bootstrap) if [ -z "${2}" ]; then usage @@ -121,14 +159,19 @@ while [ "$#" -gt 0 ]; do usage else TARGET="${1}" - RELEASE="${2}" + ACTION="${2}" + RELEASE="${3}" fi - if [ -z "${DRY_RUN}" ]; then - DRY_RUN=0 - fi - set_target_single "${TARGET}" - update_jail_etc "${TARGET}" "${RELEASE}" - shift "$#" + case "${ACTION}" in + resolve) + resolve_conflicts "${TARGET}" + shift "$#" + ;; + update) + update_jail_etc "${TARGET}" "${RELEASE}" + shift "$#" + ;; + esac ;; esac done From 6ce41919e4d80dcd24b835f17bd4ec73cc035137 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 9 Jan 2025 15:10:23 -0700 Subject: [PATCH 026/141] etcupdate: add diff mode --- usr/local/share/bastille/etcupdate.sh | 54 +++++++++++++++++---------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index ed579597..2f44013b 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -46,12 +46,14 @@ EOF bootstrap_etc_release() { local _release="${1}" local _current="$(sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives | awk -F': ' '{print $2}')" - if ls -A "${bastille_releasesdir}/${_release}/usr/src" 2>/dev/null; then + if ! ls -A "${bastille_releasesdir}/${_release}/usr/src" 2>/dev/null; then sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives=src - if ! bastille bootstrap "${_release}"; then - error_notify "Failed to bootstrap etcupdate: ${_release}" + if ! bastille bootstrap "${_release}" > /dev/null; then + sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}" + error_exit "Failed to bootstrap etcupdate: ${_release}" + else + sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}" fi - sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}" fi } @@ -68,7 +70,7 @@ bootstrap_etc_tarball() { rm -f "${bastille_cachedir}/${_release}.tbz2" echo "Building tarball, please wait..." if ! etcupdate build -d /tmp/etcupdate -s ${bastille_releasesdir}/${_release}/usr/src ${bastille_cachedir}/${_release}.tbz2; then - error_exit "Failed to build etcupdate tarball \"${_release}.tbz2\"" + error_exit "Failed to build etcupdate tarball: ${_release}.tbz2" else info "Etcupdate bootstrap complete: ${_release}" fi @@ -77,13 +79,19 @@ bootstrap_etc_tarball() { fi } +diff_review() { + local _jail="${1}" + info "[_jail]: diff" + etcupdate diff -D "${bastille_jailsdir}/${_jail}/root" +} + resolve_conflicts() { local _jail="${1}" if [ "${DRY_RUN}" -eq 1 ]; then - info "[_jail]: --dry-run" + info "[_jail]: resolve --dry-run" etcupdate resolve -n -D "${bastille_jailsdir}/${_jail}/root" else - info "[_jail]:" + info "[_jail]: resolve" etcupdate resolve -D "${bastille_jailsdir}/${_jail}/root" fi } @@ -92,10 +100,10 @@ update_jail_etc() { local _jail="${1}" local _release="${2}" if [ "${DRY_RUN}" -eq 1 ]; then - info "[_jail]: --dry-run" + info "[_jail]: update --dry-run" etcupdate -n -D "${bastille_jailsdir}/${_jail}/root" -t ${bastille_cachedir}/${_release}.tbz2 else - info "[_jail]:" + info "[_jail]: update" etcupdate -D "${bastille_jailsdir}/${_jail}/root" -t ${bastille_cachedir}/${_release}.tbz2 fi } @@ -161,17 +169,25 @@ while [ "$#" -gt 0 ]; do TARGET="${1}" ACTION="${2}" RELEASE="${3}" + set_target_single "${TARGET}" + case "${ACTION}" in + diff) + diff_review "${TARGET}" + shift "$#" + ;; + resolve) + resolve_conflicts "${TARGET}" + shift "$#" + ;; + update) + update_jail_etc "${TARGET}" "${RELEASE}" + shift "$#" + ;; + *) + error_exit "Unknown action: \"${ACTION}\"" + ;; + esac fi - case "${ACTION}" in - resolve) - resolve_conflicts "${TARGET}" - shift "$#" - ;; - update) - update_jail_etc "${TARGET}" "${RELEASE}" - shift "$#" - ;; - esac ;; esac done From b90a83bfb72984c0640e69cd016a26b457c913ea Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 9 Jan 2025 15:11:19 -0700 Subject: [PATCH 027/141] etcupdate: help message include diff mode --- usr/local/share/bastille/etcupdate.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index 2f44013b..c5d1c397 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -31,7 +31,7 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_notify "Usage: bastille etcupdate [option(s)] [bootstrap|TARGET] [update RELEASE|resolve]" + error_notify "Usage: bastille etcupdate [option(s)] [bootstrap|TARGET] [diff|resolve|update RELEASE]" cat << EOF Options: From e6e60a3a32b976ea595c45d021f31b175b1f1566 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 9 Jan 2025 15:12:23 -0700 Subject: [PATCH 028/141] common: update set_target_single --- usr/local/share/bastille/common.sh | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index b9b0986f..6e61f5c5 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -190,13 +190,28 @@ set_target_single() { local _TARGET="${1}" if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then error_exit "[all|ALL] not supported with this command." - else - check_target_exists "${_TARGET}" || error_exit "Jail not found \"${_TARGET}\"" - JAILS="${_TARGET}" - TARGET="${_TARGET}" - export JAILS - export TARGET + elif [ "$(echo ${_TARGET} | wc -w)" -gt 1 ]; then + error_exit "Error: Command only supports a single TARGET." + elif echo "${_TARGET}" | grep -Eq '^[0-9]+$'; then + if get_jail_name "${_TARGET}" > /dev/null; then + _TARGET="$(get_jail_name ${_TARGET})" + else + error_exit "Error: JID \"${_TARGET}\" not found. Is jail running?" + fi + elif + ! check_target_exists "${_TARGET}"; then + if jail_autocomplete "${_TARGET}" > /dev/null; then + _TARGET="$(jail_autocomplete ${_TARGET})" + elif [ $? -eq 2 ]; then + error_exit "Jail not found \"${_TARGET}\"" + else + exit 1 + fi fi + TARGET="${_TARGET}" + JAILS="${_TARGET}" + export TARGET + export JAILS } target_all_jails() { From e4b5273835ce2efdb5b57b8104089a4f08b86e3b Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 9 Jan 2025 15:41:23 -0700 Subject: [PATCH 029/141] etcupdate: fix accidentally deleted error message --- usr/local/share/bastille/etcupdate.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index c5d1c397..1f143c29 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -99,6 +99,9 @@ resolve_conflicts() { update_jail_etc() { local _jail="${1}" local _release="${2}" + if [ ! -f ${bastille_cachedir}/${_release}.tbz2 ]; then + error_exit "Error: Please run \"bastille etcupdate bootstrap RELEASE\" first." + fi if [ "${DRY_RUN}" -eq 1 ]; then info "[_jail]: update --dry-run" etcupdate -n -D "${bastille_jailsdir}/${_jail}/root" -t ${bastille_cachedir}/${_release}.tbz2 From 8882c23b185e3ae1bb7c5edad873839d278399a6 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:30:29 -0700 Subject: [PATCH 030/141] etcupdate: code optimize (usage if no RELEASE) --- usr/local/share/bastille/etcupdate.sh | 55 ++++++++++++++------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index 1f143c29..d689f323 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -111,10 +111,6 @@ update_jail_etc() { fi } -if [ "$#" -lt 2 ] || [ "$#" -gt 4 ]; then - usage -fi - # Handle options. DRY_RUN=0 FORCE=0 @@ -152,6 +148,10 @@ while [ "$#" -gt 0 ]; do esac done +if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then + usage +fi + # Main commands while [ "$#" -gt 0 ]; do case "${1}" in @@ -166,31 +166,32 @@ while [ "$#" -gt 0 ]; do fi ;; *) - if [ -z "${2}" ]; then - usage - else - TARGET="${1}" - ACTION="${2}" - RELEASE="${3}" - set_target_single "${TARGET}" - case "${ACTION}" in - diff) - diff_review "${TARGET}" - shift "$#" - ;; - resolve) - resolve_conflicts "${TARGET}" - shift "$#" - ;; - update) + TARGET="${1}" + ACTION="${2}" + RELEASE="${3}" + set_target_single "${TARGET}" + case "${ACTION}" in + diff) + diff_review "${TARGET}" + shift "$#" + ;; + resolve) + resolve_conflicts "${TARGET}" + shift "$#" + ;; + update) + if [ -z "${RELEASE}" ]; then + usage + else update_jail_etc "${TARGET}" "${RELEASE}" shift "$#" - ;; - *) - error_exit "Unknown action: \"${ACTION}\"" + fi ;; - esac - fi - ;; + *) + error_exit "Unknown action: \"${ACTION}\"" + ;; + esac + fi + ;; esac done From cca43cb43688f716f7de3f2e6eb0efec9bf89fb9 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:34:15 -0700 Subject: [PATCH 031/141] =?UTF-8?q?etcupdate:=20fix=20=E2=80=9Cfi=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- usr/local/share/bastille/etcupdate.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index d689f323..716e26ea 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -188,10 +188,9 @@ while [ "$#" -gt 0 ]; do fi ;; *) - error_exit "Unknown action: \"${ACTION}\"" - ;; + error_exit "Unknown action: \"${ACTION}\"" + ;; esac - fi ;; esac done From 894e5ef5f6c148b4bdc88215b07b50a7784f7633 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:37:48 -0700 Subject: [PATCH 032/141] etcupdate: fix ;; spacing --- usr/local/share/bastille/etcupdate.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index 716e26ea..7126b905 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -191,6 +191,6 @@ while [ "$#" -gt 0 ]; do error_exit "Unknown action: \"${ACTION}\"" ;; esac - ;; + ;; esac done From fb145b344185a2d61d857a21433ba15b73a58801 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 9 Jan 2025 20:47:39 -0700 Subject: [PATCH 033/141] common: error when jail name is a number --- usr/local/share/bastille/common.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 4e0272b3..9d6efd54 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -147,7 +147,7 @@ set_target() { target_all_jails else for _jail in ${_TARGET}; do - if echo "${_jail}" | grep -Eq '^[0-9]+$'; then + if [ ! -d "${bastille_jailsdir}/${_TARGET}" ] && [ echo "${_jail}" | grep -Eq '^[0-9]+$' ]; then if get_jail_name "${_jail}" > /dev/null; then _jail="$(get_jail_name ${_jail})" else @@ -172,12 +172,11 @@ set_target() { set_target_single() { local _TARGET="${1}" - local _status=0 if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then error_exit "[all|ALL] not supported with this command." elif [ "$(echo ${_TARGET} | wc -w)" -gt 1 ]; then error_exit "Error: Command only supports a single TARGET." - elif echo "${_TARGET}" | grep -Eq '^[0-9]+$'; then + elif [ ! -d "${bastille_jailsdir}/${_TARGET}" ] && [ echo "${_TARGET}" | grep -Eq '^[0-9]+$' ]; then if get_jail_name "${_TARGET}" > /dev/null; then _TARGET="$(get_jail_name ${_TARGET})" else @@ -188,7 +187,7 @@ set_target_single() { if jail_autocomplete "${_TARGET}" > /dev/null; then _TARGET="$(jail_autocomplete ${_TARGET})" elif [ $? -eq 2 ]; then - error_exit "Jail not found \"${_jail}\"" + error_exit "Jail not found \"${_TARGET}\"" else exit 1 fi From d1e475e3d190b34f3e7817a69743479a2201ed62 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 9 Jan 2025 23:30:48 -0700 Subject: [PATCH 034/141] common: fix brackets [] --- usr/local/share/bastille/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 9d6efd54..5b3611db 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -147,7 +147,7 @@ set_target() { target_all_jails else for _jail in ${_TARGET}; do - if [ ! -d "${bastille_jailsdir}/${_TARGET}" ] && [ echo "${_jail}" | grep -Eq '^[0-9]+$' ]; then + if [ ! -d "${bastille_jailsdir}/${_TARGET}" ] && echo "${_jail}" | grep -Eq '^[0-9]+$'; then if get_jail_name "${_jail}" > /dev/null; then _jail="$(get_jail_name ${_jail})" else From f55335e21cebae94344710d60273215d24f5fa87 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 9 Jan 2025 23:31:23 -0700 Subject: [PATCH 035/141] common: fix [] --- usr/local/share/bastille/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 5b3611db..3e29683c 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -176,7 +176,7 @@ set_target_single() { error_exit "[all|ALL] not supported with this command." elif [ "$(echo ${_TARGET} | wc -w)" -gt 1 ]; then error_exit "Error: Command only supports a single TARGET." - elif [ ! -d "${bastille_jailsdir}/${_TARGET}" ] && [ echo "${_TARGET}" | grep -Eq '^[0-9]+$' ]; then + elif [ ! -d "${bastille_jailsdir}/${_TARGET}" ] && echo "${_TARGET}" | grep -Eq '^[0-9]+$'; then if get_jail_name "${_TARGET}" > /dev/null; then _TARGET="$(get_jail_name ${_TARGET})" else From cd330363c255493c5a932eea7c7171b883c905c9 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 10 Jan 2025 00:14:25 -0700 Subject: [PATCH 036/141] etcupdate: jail var missing --- usr/local/share/bastille/etcupdate.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index 7126b905..84ea57d1 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -81,17 +81,17 @@ bootstrap_etc_tarball() { diff_review() { local _jail="${1}" - info "[_jail]: diff" + info "[${_jail}]: etcupdate --diff mode" etcupdate diff -D "${bastille_jailsdir}/${_jail}/root" } resolve_conflicts() { local _jail="${1}" if [ "${DRY_RUN}" -eq 1 ]; then - info "[_jail]: resolve --dry-run" + info "[${_jail}]: etcupdate resolve --dry-run" etcupdate resolve -n -D "${bastille_jailsdir}/${_jail}/root" else - info "[_jail]: resolve" + info "[${_jail}]: etcupdate resolve" etcupdate resolve -D "${bastille_jailsdir}/${_jail}/root" fi } @@ -103,10 +103,10 @@ update_jail_etc() { error_exit "Error: Please run \"bastille etcupdate bootstrap RELEASE\" first." fi if [ "${DRY_RUN}" -eq 1 ]; then - info "[_jail]: update --dry-run" + info "[${_jail}]: etcupdate update --dry-run" etcupdate -n -D "${bastille_jailsdir}/${_jail}/root" -t ${bastille_cachedir}/${_release}.tbz2 else - info "[_jail]: update" + info "[${_jail}]: etcupdate update" etcupdate -D "${bastille_jailsdir}/${_jail}/root" -t ${bastille_cachedir}/${_release}.tbz2 fi } From 397b13bc233c2558d92a3e118cc890ed6ba1f169 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 10 Jan 2025 00:18:47 -0700 Subject: [PATCH 037/141] etcupdate: remove -n option from resolve mode --- usr/local/share/bastille/etcupdate.sh | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index 84ea57d1..87e6dc2a 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -87,13 +87,8 @@ diff_review() { resolve_conflicts() { local _jail="${1}" - if [ "${DRY_RUN}" -eq 1 ]; then - info "[${_jail}]: etcupdate resolve --dry-run" - etcupdate resolve -n -D "${bastille_jailsdir}/${_jail}/root" - else - info "[${_jail}]: etcupdate resolve" - etcupdate resolve -D "${bastille_jailsdir}/${_jail}/root" - fi + info "[${_jail}]: etcupdate resolve" + etcupdate resolve -D "${bastille_jailsdir}/${_jail}/root" } update_jail_etc() { From 86c5b4928b2252209c85204067da0a96246106ef Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 10 Jan 2025 08:56:32 -0700 Subject: [PATCH 038/141] etcupdate: warn on -d for diff/resolve --- usr/local/share/bastille/etcupdate.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index 87e6dc2a..04990c34 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -81,12 +81,18 @@ bootstrap_etc_tarball() { diff_review() { local _jail="${1}" + if [ "${DRY_RUN}" -eq 1 ]; then + warn "Warning: diff mode does not support [-d|--dryrun]" + fi info "[${_jail}]: etcupdate --diff mode" etcupdate diff -D "${bastille_jailsdir}/${_jail}/root" } resolve_conflicts() { local _jail="${1}" + if [ "${DRY_RUN}" -eq 1 ]; then + warn "Warning: resolve mode does not support [-d|--dryrun]" + fi info "[${_jail}]: etcupdate resolve" etcupdate resolve -D "${bastille_jailsdir}/${_jail}/root" } From 753c537e52fa30287c9fd09a7fd3c8bc50622a55 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 12:06:30 -0700 Subject: [PATCH 039/141] mount: allow [ro|rw|rq|sw|xx] as available mount options --- usr/local/share/bastille/mount.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index ba66ae8b..73d5d5e7 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -89,8 +89,8 @@ elif [ ! -e "${_hostpath}" ] || [ "${_type}" != "nullfs" ]; then usage fi -# Mount permissions,options need to start with "ro" or "rw" -if ! echo "${_perms}" | grep -Eq 'r[w|o],.*$'; then +# Mount permissions,options need to include at least on of "ro, rw, rq, sw, xx" +if ! echo "${_perms}" | grep -Eq '[ro|rw|rq|sw|xx]'; then error_notify "Detected invalid mount permissions in FSTAB." warn "Format: /host/path /jail/path nullfs ro 0 0" warn "Read: ${_fstab}" From fa4466eb7f479c79737760a282601cd0325faa0e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 12:07:59 -0700 Subject: [PATCH 040/141] mount: docs, allow all fs type options --- docs/chapters/subcommands/mount.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/chapters/subcommands/mount.rst b/docs/chapters/subcommands/mount.rst index cabe779c..dfbbd526 100644 --- a/docs/chapters/subcommands/mount.rst +++ b/docs/chapters/subcommands/mount.rst @@ -10,7 +10,7 @@ Syntax follows standard `/etc/fstab` format: Usage: bastille mount TARGET HOST_PATH JAIL_PATH [filesystem_type options dump pass_number] -The 'options' string can include a comma-separated list of mount options, but must start with 'ro' or 'rw'. +The 'options' string can include a comma-separated list of mount options, but must include at least one of (rw,ro,rq.sw,xx) according to fstab documentation. Example: Mount a tmpfs filesystem with options. .. code-block:: shell From f3123bf08de1a6982b3479c2bdae96e2e28d83dd Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 12:08:24 -0700 Subject: [PATCH 041/141] mount: Docs, typo . > , --- docs/chapters/subcommands/mount.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/chapters/subcommands/mount.rst b/docs/chapters/subcommands/mount.rst index dfbbd526..a5fbc930 100644 --- a/docs/chapters/subcommands/mount.rst +++ b/docs/chapters/subcommands/mount.rst @@ -10,7 +10,7 @@ Syntax follows standard `/etc/fstab` format: Usage: bastille mount TARGET HOST_PATH JAIL_PATH [filesystem_type options dump pass_number] -The 'options' string can include a comma-separated list of mount options, but must include at least one of (rw,ro,rq.sw,xx) according to fstab documentation. +The 'options' string can include a comma-separated list of mount options, but must include at least one of (rw,ro,rq,sw,xx) according to fstab documentation. Example: Mount a tmpfs filesystem with options. .. code-block:: shell From e33dd04ad1c0f9d16b391361d4583177131679b2 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 12:10:27 -0700 Subject: [PATCH 042/141] mount: Docs, one more typo "on > one" --- usr/local/share/bastille/mount.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index 73d5d5e7..c6bf5bf8 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -89,7 +89,7 @@ elif [ ! -e "${_hostpath}" ] || [ "${_type}" != "nullfs" ]; then usage fi -# Mount permissions,options need to include at least on of "ro, rw, rq, sw, xx" +# Mount permissions,options need to include at least one of "ro, rw, rq, sw, xx" if ! echo "${_perms}" | grep -Eq '[ro|rw|rq|sw|xx]'; then error_notify "Detected invalid mount permissions in FSTAB." warn "Format: /host/path /jail/path nullfs ro 0 0" From 5409d8eab3cc96d7ebfd1b1825d8adff7ada9c05 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 15:38:17 -0700 Subject: [PATCH 043/141] top: add auto mode --- usr/local/share/bastille/top.sh | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/usr/local/share/bastille/top.sh b/usr/local/share/bastille/top.sh index bd82d153..8911473f 100644 --- a/usr/local/share/bastille/top.sh +++ b/usr/local/share/bastille/top.sh @@ -38,25 +38,37 @@ usage() { cat << EOF Options: - -f | --force -- Start the jail if it is stopped. + -a | --auto Auto mode. Start/stop jail(s) if required. + -x | --debug Enable debug mode. EOF exit 1 } # Handle options. -FORCE=0 +AUTO=0 while [ "$#" -gt 0 ]; do case "${1}" in -h|--help|help) usage ;; - -f|--force) - FORCE=1 + -a|--auto) + AUTO=1 + shift + ;; + -x|--debug) + enable_debug shift ;; -*) - error_exit "Unknown option: \"${1}\"" + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + a) AUTO=1 ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" ;; + esac + done + shift ;; *) break @@ -74,10 +86,10 @@ bastille_root_check set_target_single "${TARGET}" info "[${TARGET}]:" -check_target_is_running "${TARGET}" || if [ "${FORCE}" -eq 1 ]; then +check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then bastille start "${TARGET}" else error_notify "Jail is not running." - error_continue "Use [-f|--force] to force start the jail." + error_continue "Use [-a|--auto] to auto-start the jail." fi jexec -l "${TARGET}" /usr/bin/top From 38e0e90e10150ca8c9deff763f3ccb2bbf43248f Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 15:40:10 -0700 Subject: [PATCH 044/141] htop: add auto mod --- usr/local/share/bastille/htop.sh | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/usr/local/share/bastille/htop.sh b/usr/local/share/bastille/htop.sh index 4449edef..d6b108d8 100644 --- a/usr/local/share/bastille/htop.sh +++ b/usr/local/share/bastille/htop.sh @@ -34,29 +34,41 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille htop [option(s)] TARGET" + error_notify "Usage: bastille htop [option(s)] TARGET" cat << EOF Options: - -f | --force -- Start the jail if it is stopped. + -a | --auto Auto mode. Start/stop jail(s) if required. + -x | --debug Enable debug mode. EOF exit 1 } # Handle options. -FORCE=0 +AUTO=0 while [ "$#" -gt 0 ]; do case "${1}" in -h|--help|help) usage ;; - -f|--force) - FORCE=1 + -a|--auto) + AUTO=1 + shift + ;; + -x|--debug) + enable_debug shift ;; -*) - error_exit "Unknown option: \"${1}\"" + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + a) AUTO=1 ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" + esac + done + shift ;; *) break @@ -74,15 +86,14 @@ bastille_root_check set_target_single "${TARGET}" info "[${TARGET}]:" -check_target_is_running "${TARGET}" || if [ "${FORCE}" -eq 1 ]; then +check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then bastille start "${TARGET}" else error_notify "Jail is not running." - error_continue "Use [-f|--force] to force start the jail." + error_continue "Use [-a|--auto] to auto-start the jail." fi -bastille_jail_path="${bastille_jailsdir}/${TARGET}/root" -if [ ! -x "${bastille_jail_path}/usr/local/bin/htop" ]; then +if [ ! -x "${bastille_jailsdir}/${TARGET}/root/usr/local/bin/htop" ]; then error_notify "htop not found on ${TARGET}." elif [ -x "${bastille_jail_path}/usr/local/bin/htop" ]; then jexec -l ${TARGET} /usr/local/bin/htop From 18a6fecad5ca25b57c13f3f8363363056575c44d Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 15:40:32 -0700 Subject: [PATCH 045/141] top: remove trailing ;; --- usr/local/share/bastille/top.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/top.sh b/usr/local/share/bastille/top.sh index 8911473f..ef2a8bcb 100644 --- a/usr/local/share/bastille/top.sh +++ b/usr/local/share/bastille/top.sh @@ -65,7 +65,7 @@ while [ "$#" -gt 0 ]; do case ${_opt} in a) AUTO=1 ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "Unknown Option: \"${1}\"" esac done shift From bc0971914515b30aff71bab1c135fca1169ae824 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 15:41:36 -0700 Subject: [PATCH 046/141] docs: top update for clarity --- docs/chapters/subcommands/top.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/chapters/subcommands/top.rst b/docs/chapters/subcommands/top.rst index 16df8682..77e7f831 100644 --- a/docs/chapters/subcommands/top.rst +++ b/docs/chapters/subcommands/top.rst @@ -2,7 +2,7 @@ top === -This one runs `top` in that container. +This command runs `top` in the targeted jail. .. image:: ../../images/top.png From 6ea0c712c4522bce22a5d2171bd1c0747aadf2d9 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 15:43:15 -0700 Subject: [PATCH 047/141] docs: htop update for clarity --- docs/chapters/subcommands/htop.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/chapters/subcommands/htop.rst b/docs/chapters/subcommands/htop.rst index d3493be2..1fcb8bdb 100644 --- a/docs/chapters/subcommands/htop.rst +++ b/docs/chapters/subcommands/htop.rst @@ -2,8 +2,8 @@ htop ==== -This one runs `htop` inside the container. -note: won't work if you don't have htop installed in the container. +This command runs `htop` in the targeted jail. +Requires htop to be installed in the jail. .. image:: ../../images/htop.png From 30767656c6d02d883d544723c64cb990eaec7ad4 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:00:10 -0700 Subject: [PATCH 048/141] docs: document JID login for console --- docs/chapters/subcommands/console.rst | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/docs/chapters/subcommands/console.rst b/docs/chapters/subcommands/console.rst index b1a218eb..966e066c 100644 --- a/docs/chapters/subcommands/console.rst +++ b/docs/chapters/subcommands/console.rst @@ -2,8 +2,7 @@ console ======= -This sub-command launches a login shell into the container. Default is password-less -root login. +This sub-command launches a login shell into the container. Default is password-less root login. .. code-block:: shell @@ -11,6 +10,23 @@ root login. [folsom]: root@folsom:~ # +TARGET can also be a running jails JID value. + + ishmael ~ # bastille list + JID IP Address Hostname Path + 1 10.1.2.3 ishmael /usr/local/bastille/jails/ishmael/root + ishmael ~ # bastille console 1 + [ishmael]: + root@ishmael:~ # + At this point you are logged in to the container and have full shell access. The system is yours to use and/or abuse as you like. Any changes made inside the container are limited to the container. + +.. code-block:: shell + + "Usage: bastille console [option(s)] TARGET [user]" + Options: + + -a | --auto Auto mode. Start/stop jail(s) if required. + -x | --debug Enable debug mode. From 3674c847fb310cd86a5e6dedfed0ee04bb479f32 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:00:34 -0700 Subject: [PATCH 049/141] docs: add code block for console --- docs/chapters/subcommands/console.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/chapters/subcommands/console.rst b/docs/chapters/subcommands/console.rst index 966e066c..264a87b5 100644 --- a/docs/chapters/subcommands/console.rst +++ b/docs/chapters/subcommands/console.rst @@ -12,6 +12,8 @@ This sub-command launches a login shell into the container. Default is password- TARGET can also be a running jails JID value. +.. code-block:: shell + ishmael ~ # bastille list JID IP Address Hostname Path 1 10.1.2.3 ishmael /usr/local/bastille/jails/ishmael/root From 228bb3b8cef36c703f758a2a3de9e0caade11665 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:44:01 -0700 Subject: [PATCH 050/141] cp: update to use new functions in common.sh --- usr/local/share/bastille/cp.sh | 80 ++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/usr/local/share/bastille/cp.sh b/usr/local/share/bastille/cp.sh index d7fc174b..0dd0b0b0 100644 --- a/usr/local/share/bastille/cp.sh +++ b/usr/local/share/bastille/cp.sh @@ -34,49 +34,63 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille cp [OPTION] TARGET HOST_PATH CONTAINER_PATH" + error_notify "Usage: bastille cp [option(s)] TARGET HOST_PATH JAIL_PATH" + cat << EOF + Options: + + -q | --quiet Suppress output. + -x | --debug Enable debug mode. + +EOF + exit 1 } -CPSOURCE="${1}" -CPDEST="${2}" +# Handle options. +OPTION="-av" +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -q|--quiet) + OPTION="-a" + shift + ;; + -x|--debug) + enable_debug + shift + ;; + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + q) OPTION="-a" ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" ;; + esac + done + shift + ;; + *) + break + ;; + esac +done -# Handle special-case commands first. -case "$1" in -help|-h|--help) - usage - ;; --q|--quiet) - OPTION="${1}" - CPSOURCE="${2}" - CPDEST="${3}" - ;; -esac - -if [ $# -ne 2 ]; then +if [ "$#" -ne 3 ]; then usage fi -bastille_root_check +TARGET="${1}" +CPSOURCE="${2}" +CPDEST="${3}" -case "${OPTION}" in - -q|--quiet) - OPTION="-a" - ;; - *) - OPTION="-av" - ;; -esac +bastille_root_check +set_target "${TARGET}" for _jail in ${JAILS}; do info "[${_jail}]:" bastille_jail_path="${bastille_jailsdir}/${_jail}/root" - cp "${OPTION}" "${CPSOURCE}" "${bastille_jail_path}/${CPDEST}" - RETURN="$?" - if [ "${TARGET}" = "ALL" ]; then - # Display the return status for reference - echo -e "Returned: ${RETURN}\n" - else - echo - return "${RETURN}" + if ! cp "${OPTION}" "${CPSOURCE}" "${bastille_jail_path}${CPDEST}"; then + error_continue "CP failed: ${CPSOURCE} -> ${bastille_jail_path}${CPDEST}" fi done From 6040308270b8d6c572a0c288d6422534e8ce80fe Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:46:30 -0700 Subject: [PATCH 051/141] rcp: update to use new functions --- usr/local/share/bastille/rcp.sh | 79 ++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/usr/local/share/bastille/rcp.sh b/usr/local/share/bastille/rcp.sh index a3b1cda1..7b313577 100644 --- a/usr/local/share/bastille/rcp.sh +++ b/usr/local/share/bastille/rcp.sh @@ -34,46 +34,63 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille rcp [OPTION] TARGET CONTAINER_PATH HOST_PATH" + error_notify "Usage: bastille rcp [option(s)] TARGET JAIL_PATH HOST_PATH" + cat << EOF + Options: + + -q | --quiet Suppress output. + -x | --debug Enable debug mode. + +EOF + exit 1 } -CPSOURCE="${1}" -CPDEST="${2}" +# Handle options. +OPTION="-av" +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -q|--quiet) + OPTION="-a" + shift + ;; + -x|--debug) + enable_debug + shift + ;; + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + q) OPTION="-a" ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" ;; + esac + done + shift + ;; + *) + break + ;; + esac +done -# Handle special-case commands first. -case "$1" in -help|-h|--help) - usage - ;; --q|--quiet) - OPTION="${1}" - CPSOURCE="${2}" - CPDEST="${3}" - ;; -esac - -if [ $# -ne 2 ]; then +if [ "$#" -ne 3 ]; then usage fi -if [ "${TARGET}" = "ALL" ]; then - usage -fi +TARGET="${1}" +CPSOURCE="${2}" +CPDEST="${3}" -case "${OPTION}" in - -q|--quiet) - OPTION="-a" - ;; - *) - OPTION="-av" - ;; -esac +bastille_root_check +set_target "${TARGET}" for _jail in ${JAILS}; do info "[${_jail}]:" bastille_jail_path="${bastille_jailsdir}/${_jail}/root" - cp "${OPTION}" "${bastille_jail_path}/${CPSOURCE}" "${CPDEST}" - RETURN="$?" - echo - return "${RETURN}" + if ! cp "${OPTION}" "${bastille_jail_path}${CPSOURCE}" "${CPDEST}"; then + error_continue "RCP failed: ${bastille_jail_path}${CPSOURCE} -> ${CPDEST}" + fi done From 14d7f4ae741c5b310d93f0914171845294da92de Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:52:39 -0700 Subject: [PATCH 052/141] docs: cp documentation update for new functions --- docs/chapters/subcommands/cp.rst | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/docs/chapters/subcommands/cp.rst b/docs/chapters/subcommands/cp.rst index 88c69cfb..e551fb92 100644 --- a/docs/chapters/subcommands/cp.rst +++ b/docs/chapters/subcommands/cp.rst @@ -6,17 +6,27 @@ This command allows efficiently copying files from host to container(s). .. code-block:: shell - ishmael ~ # bastille cp ALL /tmp/resolv.conf-cf etc/resolv.conf + ishmael ~ # bastille cp ALL /tmp/resolv.conf-cf /etc/resolv.conf [bastion]: - + /tmp/resolv.conf-cf -> /usr/local/bastille/jails/bastion/root/etc/resolv.conf [unbound0]: - + /tmp/resolv.conf-cf -> /usr/local/bastille/jails/unbound0/root/etc/resolv.conf [unbound1]: - + /tmp/resolv.conf-cf -> /usr/local/bastille/jails/unbound1/root/etc/resolv.conf [squid]: - + /tmp/resolv.conf-cf -> /usr/local/bastille/jails/squid/root/etc/resolv.conf [nginx]: - + /tmp/resolv.conf-cf -> /usr/local/bastille/jails/nginx/root/etc/resolv.conf [folsom]: + /tmp/resolv.conf-cf -> /usr/local/bastille/jails/folsom/root/etc/resolv.conf Unless you see errors reported in the output the `cp` was successful. + +.. code-block:: shell + + ishmael ~ # bastille cp help + Usage: bastille cp [option(s)] TARGET HOST_PATH JAIL_PATH + Options: + + -q | --quiet Suppress output. + -x | --debug Enable debug mode. From c67ab1879c1e8d14defd6cbc74834099452ba6c9 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:59:41 -0700 Subject: [PATCH 053/141] docs: add rcp documentation --- docs/chapters/subcommands/rcp.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/chapters/subcommands/rcp.rst diff --git a/docs/chapters/subcommands/rcp.rst b/docs/chapters/subcommands/rcp.rst new file mode 100644 index 00000000..7b9945d7 --- /dev/null +++ b/docs/chapters/subcommands/rcp.rst @@ -0,0 +1,22 @@ +=== +rcp +=== + +This command allows copying files from a single jail to the host. + +.. code-block:: shell + + ishmael ~ # bastille rcp bastion /tmp/myfile /temp + [bastion]: + /usr/local/bastille/jails/bastion/root/tmp/myfile -> /temp/myfile + +Unless you see errors reported in the output the `rcp` was successful. + +.. code-block:: shell + + ishmael ~ # bastille rcp help + Usage: bastille rcp [option(s)] TARGET JAIL_PATH HOST_PATH + Options: + + -q | --quiet Suppress output. + -x | --debug Enable debug mode. From 816f24331af490eb5be856abbb6b3ace4e9e1159 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 17:20:10 -0700 Subject: [PATCH 054/141] cp: trim double // to / --- usr/local/share/bastille/cp.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/cp.sh b/usr/local/share/bastille/cp.sh index 0dd0b0b0..a1dc0c15 100644 --- a/usr/local/share/bastille/cp.sh +++ b/usr/local/share/bastille/cp.sh @@ -89,8 +89,9 @@ set_target "${TARGET}" for _jail in ${JAILS}; do info "[${_jail}]:" - bastille_jail_path="${bastille_jailsdir}/${_jail}/root" - if ! cp "${OPTION}" "${CPSOURCE}" "${bastille_jail_path}${CPDEST}"; then - error_continue "CP failed: ${CPSOURCE} -> ${bastille_jail_path}${CPDEST}" + host_path="${CPSOURCE}" + jail_path="$(echo ${bastille_jailsdir}/${_jail}/root/${CPDEST} | sed 's#//#/#g')" + if ! cp "${OPTION}" "${host_path}" "${jail_path}"; then + error_continue "CP failed: ${host_path} -> ${jail_path}" fi done From f65b8c3ebfb8a0e5e1fd828d2a4ed9aa611f71a5 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 11 Jan 2025 17:20:54 -0700 Subject: [PATCH 055/141] rcp: trim // to / and allow only single target --- usr/local/share/bastille/rcp.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/usr/local/share/bastille/rcp.sh b/usr/local/share/bastille/rcp.sh index 7b313577..ec1c5bd5 100644 --- a/usr/local/share/bastille/rcp.sh +++ b/usr/local/share/bastille/rcp.sh @@ -85,12 +85,13 @@ CPSOURCE="${2}" CPDEST="${3}" bastille_root_check -set_target "${TARGET}" +set_target_single "${TARGET}" for _jail in ${JAILS}; do info "[${_jail}]:" - bastille_jail_path="${bastille_jailsdir}/${_jail}/root" - if ! cp "${OPTION}" "${bastille_jail_path}${CPSOURCE}" "${CPDEST}"; then - error_continue "RCP failed: ${bastille_jail_path}${CPSOURCE} -> ${CPDEST}" + host_path="${CPDEST}" + jail_path="$(echo ${bastille_jailsdir}/${_jail}/root/${CPSOURCE} | sed 's#//#/#g')" + if ! cp "${OPTION}" "${jail_path}" "${host_path}"; then + error_continue "RCP failed: ${jail_path} -> ${host_path}" fi done From 8e73e6f18806e117636a2350de9a5a66b8920c1d Mon Sep 17 00:00:00 2001 From: tschettervictor Date: Sun, 12 Jan 2025 11:16:51 -0700 Subject: [PATCH 056/141] cp: include rcp in cp and add jail mode --- README.md | 3 +- docs/chapters/subcommands/rcp.rst | 22 ------- usr/local/bin/bastille | 3 +- usr/local/share/bastille/cp.sh | 78 ++++++++++++++++++++----- usr/local/share/bastille/rcp.sh | 97 ------------------------------- 5 files changed, 65 insertions(+), 138 deletions(-) delete mode 100644 docs/chapters/subcommands/rcp.rst delete mode 100644 usr/local/share/bastille/rcp.sh diff --git a/README.md b/README.md index 21746469..1dcc5c7c 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ Available Commands: config Get or set a config value for the targeted container(s). console Console into a running container. convert Convert a Thin container into a Thick container. - cp cp(1) files from host to targeted container(s). + cp cp(1) files from host or container to host or targeted container(s). create Create a new thin container or a thick container if -T|--thick option specified. destroy Destroy a stopped container or a FreeBSD release. edit Edit container configuration files (advanced). @@ -75,7 +75,6 @@ Available Commands: mount Mount a volume inside the targeted container(s). pkg Manipulate binary packages within targeted container(s). See pkg(8). rdr Redirect host port to container port. - rcp reverse cp(1) files from a single container to the host. rename Rename a container. restart Restart a running container. service Manage services within targeted container(s). diff --git a/docs/chapters/subcommands/rcp.rst b/docs/chapters/subcommands/rcp.rst deleted file mode 100644 index 7b9945d7..00000000 --- a/docs/chapters/subcommands/rcp.rst +++ /dev/null @@ -1,22 +0,0 @@ -=== -rcp -=== - -This command allows copying files from a single jail to the host. - -.. code-block:: shell - - ishmael ~ # bastille rcp bastion /tmp/myfile /temp - [bastion]: - /usr/local/bastille/jails/bastion/root/tmp/myfile -> /temp/myfile - -Unless you see errors reported in the output the `rcp` was successful. - -.. code-block:: shell - - ishmael ~ # bastille rcp help - Usage: bastille rcp [option(s)] TARGET JAIL_PATH HOST_PATH - Options: - - -q | --quiet Suppress output. - -x | --debug Enable debug mode. diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index c5442daf..3799429c 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -95,7 +95,7 @@ Available Commands: config Get or set a config value for the targeted container(s). console Console into a running container. convert Convert a Thin container into a Thick container. - cp cp(1) files from host to targeted container(s). + cp cp(1) files from host or container to host or targeted container(s). create Create a new thin container or a thick container if -T|--thick option specified. destroy Destroy a stopped container or a FreeBSD release. edit Edit container configuration files (advanced). @@ -107,7 +107,6 @@ Available Commands: list List containers (running). mount Mount a volume inside the targeted container(s). pkg Manipulate binary packages within targeted container(s). See pkg(8). - rcp reverse cp(1) files from a single container to the host. rdr Redirect host port to container port. rename Rename a container. restart Restart a running container. diff --git a/usr/local/share/bastille/cp.sh b/usr/local/share/bastille/cp.sh index a1dc0c15..b0141327 100644 --- a/usr/local/share/bastille/cp.sh +++ b/usr/local/share/bastille/cp.sh @@ -34,24 +34,37 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_notify "Usage: bastille cp [option(s)] TARGET HOST_PATH JAIL_PATH" + error_notify "Usage: bastille cp [option(s)] TARGET SOURCE DESTINATION" cat << EOF Options: - -q | --quiet Suppress output. - -x | --debug Enable debug mode. + -j | --jail Jail mode. Copy files from jail to jail(s). + Syntax is [-j jail:srcpath jail:dstpath] + -r | --reverse Reverse copy files from jail to host. + -q | --quiet Suppress output. + -x | --debug Enable debug mode. EOF exit 1 } # Handle options. +JAIL_MODE=0 OPTION="-av" +REVERSE_MODE=0 while [ "$#" -gt 0 ]; do case "${1}" in -h|--help|help) usage ;; + -j|--jail) + JAIL_MODE=1 + shift + ;; + -r|--reverse) + REVERSE_MODE=1 + shift + ;; -q|--quiet) OPTION="-a" shift @@ -63,6 +76,8 @@ while [ "$#" -gt 0 ]; do -*) for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do case ${_opt} in + j) JAIL_MODE=1 ;; + r) REVERSE_MODE=1 ;; q) OPTION="-a" ;; x) enable_debug ;; *) error_exit "Unknown Option: \"${1}\"" ;; @@ -76,22 +91,55 @@ while [ "$#" -gt 0 ]; do esac done -if [ "$#" -ne 3 ]; then +if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then usage fi +if [ "${JAIL_MODE}" -eq 1 ]; then + SOURCE_TARGET="$(echo ${1} | awk -F":" '{print $1}')" + SOURCE_PATH="$(echo ${1} | awk -F":" '{print $2}')" + DEST_TARGET="$(echo ${2} | awk -F":" '{print $1}')" + DEST_PATH="$(echo ${2} | awk -F":" '{print $2}')" + set_target_single "${SOURCE_TARGET}" && SOURCE_TARGET="${TARGET}" + set_target "${DEST_TARGET}" && DEST_TARGET="${JAILS}" + for _jail in ${DEST_TARGET}; do + if [ "${_jail}" = "${SOURCE_TARGET}" ]; then + continue + fi + info "[${_jail}]:" + source_path="$(echo ${bastille_jailsdir}/${SOURCE_TARGET}/root/${SOURCE_PATH} | sed 's#//#/#g')" + dest_path="$(echo ${bastille_jailsdir}/${_jail}/root/${DEST_PATH} | sed 's#//#/#g')" + if ! cp "${OPTION}" "${source_path}" "${dest_path}"; then + error_continue "CP failed: ${source_path} -> ${dest_path}" + fi + done + exit +fi + TARGET="${1}" -CPSOURCE="${2}" -CPDEST="${3}" +SOURCE="${2}" +DEST="${3}" bastille_root_check -set_target "${TARGET}" -for _jail in ${JAILS}; do - info "[${_jail}]:" - host_path="${CPSOURCE}" - jail_path="$(echo ${bastille_jailsdir}/${_jail}/root/${CPDEST} | sed 's#//#/#g')" - if ! cp "${OPTION}" "${host_path}" "${jail_path}"; then - error_continue "CP failed: ${host_path} -> ${jail_path}" - fi -done +if [ "${REVERSE_MODE}" -eq 1 ]; then + set_target_single "${TARGET}" + for _jail in ${JAILS}; do + info "[${_jail}]:" + host_path="${DEST}" + jail_path="$(echo ${bastille_jailsdir}/${_jail}/root/${SOURCE} | sed 's#//#/#g')" + if ! cp "${OPTION}" "${jail_path}" "${host_path}"; then + error_exit "RCP failed: ${jail_path} -> ${host_path}" + fi + done +else + set_target "${TARGET}" + for _jail in ${JAILS}; do + info "[${_jail}]:" + host_path="${SOURCE}" + jail_path="$(echo ${bastille_jailsdir}/${_jail}/root/${DEST} | sed 's#//#/#g')" + if ! cp "${OPTION}" "${host_path}" "${jail_path}"; then + error_continue "CP failed: ${host_path} -> ${jail_path}" + fi + done +fi \ No newline at end of file diff --git a/usr/local/share/bastille/rcp.sh b/usr/local/share/bastille/rcp.sh deleted file mode 100644 index ec1c5bd5..00000000 --- a/usr/local/share/bastille/rcp.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/sh -# -# SPDX-License-Identifier: BSD-3-Clause -# -# Copyright (c) 2018-2025, Christer Edwards -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of the copyright holder nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -. /usr/local/share/bastille/common.sh -. /usr/local/etc/bastille/bastille.conf - -usage() { - error_notify "Usage: bastille rcp [option(s)] TARGET JAIL_PATH HOST_PATH" - cat << EOF - Options: - - -q | --quiet Suppress output. - -x | --debug Enable debug mode. - -EOF - exit 1 -} - -# Handle options. -OPTION="-av" -while [ "$#" -gt 0 ]; do - case "${1}" in - -h|--help|help) - usage - ;; - -q|--quiet) - OPTION="-a" - shift - ;; - -x|--debug) - enable_debug - shift - ;; - -*) - for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do - case ${_opt} in - q) OPTION="-a" ;; - x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; - esac - done - shift - ;; - *) - break - ;; - esac -done - -if [ "$#" -ne 3 ]; then - usage -fi - -TARGET="${1}" -CPSOURCE="${2}" -CPDEST="${3}" - -bastille_root_check -set_target_single "${TARGET}" - -for _jail in ${JAILS}; do - info "[${_jail}]:" - host_path="${CPDEST}" - jail_path="$(echo ${bastille_jailsdir}/${_jail}/root/${CPSOURCE} | sed 's#//#/#g')" - if ! cp "${OPTION}" "${jail_path}" "${host_path}"; then - error_continue "RCP failed: ${jail_path} -> ${host_path}" - fi -done From cab6f1a217df48e31d83723d95e91463e6d68a63 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 13 Jan 2025 08:41:14 -0700 Subject: [PATCH 057/141] =?UTF-8?q?etcupdate:=20add=20=E2=80=9C=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- usr/local/share/bastille/etcupdate.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index 04990c34..9e4f6c68 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -163,7 +163,7 @@ while [ "$#" -gt 0 ]; do RELEASE="${2}" bootstrap_etc_release "${RELEASE}" bootstrap_etc_tarball "${RELEASE}" - shift $# + shift "$#" fi ;; *) From 10822931bbbe97afa3dab9939b1e136beae0356e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 13 Jan 2025 13:19:26 -0700 Subject: [PATCH 058/141] create: Static MAC optional --- usr/local/share/bastille/create.sh | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index 77169e8f..0f47f17c 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -41,12 +41,13 @@ usage() { cat << EOF Options: - -E | --empty -- Creates an empty container, intended for custom jail builds (thin/thick/linux or unsupported). - -L | --linux -- This option is intended for testing with Linux jails, this is considered experimental. - -T | --thick -- Creates a thick container, they consume more space as they are self contained and independent. - -V | --vnet -- Enables VNET, VNET containers are attached to a virtual bridge interface for connectivity. - -C | --clone -- Creates a clone container, they are duplicates of the base release, consume low space and preserves changing data. - -B | --bridge -- Enables VNET, VNET containers are attached to a specified, already existing external bridge. + -M | --static-mac -- Generate a static MAC address for jail (VNET only). + -E | --empty -- Creates an empty container, intended for custom jail builds (thin/thick/linux or unsupported). + -L | --linux -- This option is intended for testing with Linux jails, this is considered experimental. + -T | --thick -- Creates a thick container, they consume more space as they are self contained and independent. + -V | --vnet -- Enables VNET, VNET containers are attached to a virtual bridge interface for connectivity. + -C | --clone -- Creates a clone container, they are duplicates of the base release, consume low space and preserves changing data. + -B | --bridge -- Enables VNET, VNET containers are attached to a specified, already existing external bridge. EOF exit 1 @@ -229,7 +230,7 @@ generate_vnet_jail_conf() { else devfs_ruleset_value=13 fi - NETBLOCK=$(generate_vnet_jail_netblock "$NAME" "${VNET_JAIL_BRIDGE}" "${bastille_jail_conf_interface}") + NETBLOCK=$(generate_vnet_jail_netblock "$NAME" "${VNET_JAIL_BRIDGE}" "${bastille_jail_conf_interface}" "${STATIC_MAC}") cat << EOF > "${bastille_jail_conf}" ${NAME} { enforce_statfs = 2; @@ -630,10 +631,15 @@ THICK_JAIL="" CLONE_JAIL="" VNET_JAIL="" LINUX_JAIL="" +STATIC_MAC="" # Handle and parse options while [ $# -gt 0 ]; do case "${1}" in + -M|--static-mac) + STATIC_MAC="1" + shift + ;; -E|--empty) EMPTY_JAIL="1" shift From cd8461691f812dc20a95d4b115aad76bc37e2945 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 13 Jan 2025 13:23:08 -0700 Subject: [PATCH 059/141] common: Static MAC optional --- usr/local/share/bastille/common.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 4189f07b..2a737185 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -126,6 +126,7 @@ generate_vnet_jail_netblock() { local jail_name="$1" local use_unique_bridge="$2" local external_interface="$3" + local static_mac="${4}" generate_static_mac "${jail_name}" "${external_interface}" ## determine number of containers + 1 ## iterate num and grep all jail configs @@ -148,6 +149,7 @@ generate_vnet_jail_netblock() { local uniq_epair_bridge="0" fi if [ -n "${use_unique_bridge}" ]; then + if [ -n "${static_mac}" ]; then ## generate bridge config cat <<-EOF vnet; @@ -161,7 +163,20 @@ generate_vnet_jail_netblock() { exec.poststop += "ifconfig ${external_interface} deletem e${uniq_epair_bridge}a_${jail_name}"; exec.poststop += "ifconfig e${uniq_epair_bridge}a_${jail_name} destroy"; EOF + else + cat <<-EOF + vnet; + vnet.interface = e${uniq_epair_bridge}b_${jail_name}; + exec.prestart += "ifconfig epair${uniq_epair_bridge} create"; + exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}a up name e${uniq_epair_bridge}a_${jail_name}"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}b up name e${uniq_epair_bridge}b_${jail_name}"; + exec.poststop += "ifconfig ${external_interface} deletem e${uniq_epair_bridge}a_${jail_name}"; + exec.poststop += "ifconfig e${uniq_epair_bridge}a_${jail_name} destroy"; +EOF + fi else + if [ -n "${static_mac}" ]; then ## generate config cat <<-EOF vnet; @@ -172,6 +187,15 @@ EOF exec.prestart += "ifconfig e0a_${uniq_epair} description \"vnet host interface for Bastille jail ${jail_name}\""; exec.poststop += "jib destroy ${uniq_epair}"; EOF + else + cat <<-EOF + vnet; + vnet.interface = e0b_${uniq_epair}; + exec.prestart += "jib addm ${uniq_epair} ${external_interface}"; + exec.prestart += "ifconfig e0a_${uniq_epair} description \"vnet host interface for Bastille jail ${jail_name}\""; + exec.poststop += "jib destroy ${uniq_epair}"; +EOF + fi fi } From 131c89c6f83c928c486fc1c2df90fb31d5127fdc Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 13 Jan 2025 13:25:54 -0700 Subject: [PATCH 060/141] clone: Static MAC optional --- usr/local/share/bastille/clone.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index 9dae7f44..c913db56 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -118,9 +118,13 @@ update_jailconf_vnet() { local uniq_epair_bridge="${_num}" # since we don't have access to the external_interface variable, we cat the jail.conf file to retrieve the mac prefix # we also do not use the main generate_static_mac function here - local macaddr_prefix="$(cat ${JAIL_CONFIG} | grep -m 1 ether | grep -oE '([0-9a-f]{2}(:[0-9a-f]{2}){5})' | awk -F: '{print $1":"$2":"$3}')" - local macaddr_suffix="$(echo -n ${NEWNAME} | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" - local macaddr="${macaddr_prefix}:${macaddr_suffix}" + if grep -oq ether ${JAIL_CONFIG}; then + local macaddr_prefix="$(cat ${JAIL_CONFIG} | grep -m 1 ether | grep -oE '([0-9a-f]{2}(:[0-9a-f]{2}){5})' | awk -F: '{print $1":"$2":"$3}')" + local macaddr_suffix="$(echo -n ${NEWNAME} | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" + local macaddr="${macaddr_prefix}:${macaddr_suffix}" + sed -i '' "s|ether.*:.*:.*:.*:.*:.*a\";|ether ${macaddr}a\";|" "${JAIL_CONFIG}" + sed -i '' "s|ether.*:.*:.*:.*:.*:.*b\";|ether ${macaddr}b\";|" "${JAIL_CONFIG}" + fi # Update the exec.* with uniq_epair when cloning jails. # for VNET jails sed -i '' "s|bastille\([0-9]\{1,\}\)|${uniq_epair}|g" "${JAIL_CONFIG}" @@ -128,8 +132,6 @@ update_jailconf_vnet() { sed -i '' "s|e\([0-9]\{1,\}\)b_${NEWNAME}|e${uniq_epair_bridge}b_${NEWNAME}|g" "${JAIL_CONFIG}" sed -i '' "s|epair\([0-9]\{1,\}\)|epair${uniq_epair_bridge}|g" "${JAIL_CONFIG}" sed -i '' "s|exec.prestart += \"ifconfig e0a_bastille\([0-9]\{1,\}\).*description.*|exec.prestart += \"ifconfig e0a_${uniq_epair} description \\\\\"vnet host interface for Bastille jail ${NEWNAME}\\\\\"\";|" "${JAIL_CONFIG}" - sed -i '' "s|ether.*:.*:.*:.*:.*:.*a\";|ether ${macaddr}a\";|" "${JAIL_CONFIG}" - sed -i '' "s|ether.*:.*:.*:.*:.*:.*b\";|ether ${macaddr}b\";|" "${JAIL_CONFIG}" break fi fi From 5345c2a59985e9650404827995533686465f9b98 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 13 Jan 2025 13:59:55 -0700 Subject: [PATCH 061/141] common: MAC now follows host prefix, and hashes jail+hostMAC for suffix --- usr/local/share/bastille/common.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 2a737185..afe07a5f 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -113,8 +113,8 @@ generate_static_mac() { local jail_name="${1}" local external_interface="${2}" local external_interface_mac="$(ifconfig ${external_interface} | grep ether | awk '{print $2}' | sed 's#:##g')" - local macaddr_prefix="$(echo -n "${external_interface_mac}" | sha256 | cut -b -6 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" - local macaddr_suffix="$(echo -n "${jail_name}" | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" + local macaddr_prefix="$(echo ${external_interface_mac} | cut -d':' -f1-3)" + local macaddr_suffix="$(echo -n "${external_interface_mac}${jail_name}" | sed 's#:##g' | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" if [ -z "${macaddr_prefix}" ] || [ -z "${macaddr_suffix}" ]; then error_notify "Failed to generate MAC address." fi From c9bb5132c03cea38bc58f70b7a1dc8d3a232a70c Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 13 Jan 2025 15:58:56 -0700 Subject: [PATCH 062/141] common: do not trim : from MAC too early --- usr/local/share/bastille/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index afe07a5f..2b7ea6af 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -112,7 +112,7 @@ check_target_is_stopped() { generate_static_mac() { local jail_name="${1}" local external_interface="${2}" - local external_interface_mac="$(ifconfig ${external_interface} | grep ether | awk '{print $2}' | sed 's#:##g')" + local external_interface_mac="$(ifconfig ${external_interface} | grep ether | awk '{print $2}')" local macaddr_prefix="$(echo ${external_interface_mac} | cut -d':' -f1-3)" local macaddr_suffix="$(echo -n "${external_interface_mac}${jail_name}" | sed 's#:##g' | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" if [ -z "${macaddr_prefix}" ] || [ -z "${macaddr_suffix}" ]; then From d9ef63bc60e8fd4a4be4d77a0cf2ddfaac4a98d0 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:03:30 -0700 Subject: [PATCH 063/141] clone: update "update_jail_conf_vnet" function for optional static MAC --- usr/local/share/bastille/clone.sh | 101 +++++++++++++++++++----------- 1 file changed, 65 insertions(+), 36 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index c913db56..4b01ec10 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -105,51 +105,80 @@ update_jailconf() { update_jailconf_vnet() { bastille_jail_rc_conf="${bastille_jailsdir}/${NEWNAME}/root/etc/rc.conf" - - # Determine number of containers and define an uniq_epair - local list_jails_num="$(bastille list jails | wc -l | awk '{print $1}')" - local num_range="$(expr "${list_jails_num}" + 1)" - jail_list=$(bastille list jail) - for _num in $(seq 0 "${num_range}"); do - if [ -n "${jail_list}" ]; then - if ! grep -q "e0b_bastille${_num}" "${bastille_jailsdir}"/*/jail.conf; then - if ! grep -q "epair${_num}" "${bastille_jailsdir}"/*/jail.conf; then - local uniq_epair="bastille${_num}" + # Determine number of interfaces and define a uniq_epair + local _if_list="$(grep -Eo 'epair[0-9]+|bastille[0-9]+' ${JAIL_CONFIG} | sort -u)" + for _if in ${_if_list}; do + local _epair_if_count="$(grep -Eo 'epair[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local _bastille_if_count="$(grep -Eo 'bastille[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local epair_num_range=$((_epair_if_count + 1)) + local bastille_num_range=$((_bastille_if_count + 1)) + if echo ${_if} | grep -Eoq 'epair[0-9]+'; then + # Update bridged VNET config + for _num in $(seq 0 "${epair_num_range}"); do + if ! grep -oq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then + # Update jail.conf epair name local uniq_epair_bridge="${_num}" - # since we don't have access to the external_interface variable, we cat the jail.conf file to retrieve the mac prefix - # we also do not use the main generate_static_mac function here + local _if_epaira="${_if}a" + local _if_epairb="${_if}b" + local _if_vnet="$(grep ${_if_epairb} "${bastille_jail_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" + sed -i '' "s|${_if}|epair${uniq_epair_bridge}|g" "${JAIL_CONFIG}" + # If jail had a static MAC, generate one for clone if grep -oq ether ${JAIL_CONFIG}; then - local macaddr_prefix="$(cat ${JAIL_CONFIG} | grep -m 1 ether | grep -oE '([0-9a-f]{2}(:[0-9a-f]{2}){5})' | awk -F: '{print $1":"$2":"$3}')" - local macaddr_suffix="$(echo -n ${NEWNAME} | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" - local macaddr="${macaddr_prefix}:${macaddr_suffix}" - sed -i '' "s|ether.*:.*:.*:.*:.*:.*a\";|ether ${macaddr}a\";|" "${JAIL_CONFIG}" - sed -i '' "s|ether.*:.*:.*:.*:.*:.*b\";|ether ${macaddr}b\";|" "${JAIL_CONFIG}" + local external_interface="$(grep "epair${uniq_epair_bridge}" ${JAIL_CONFIG} | grep -o '[^ ]* addm' | awk '{print $1}')" + generate_static_mac "${NEWNAME}" "${external_interface}" + sed -i '' "s|epair${uniq_epair_bridge}a ether.*:.*:.*:.*:.*:.*a\";|epair${uniq_epair}a ether ${macaddr}a\";|" "${JAIL_CONFIG}" + sed -i '' "s|epair${uniq_epair_bridge}b ether.*:.*:.*:.*:.*:.*b\";|epair${uniq_epair}b ether ${macaddr}b\";|" "${JAIL_CONFIG}" + fi + sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${JAIL_CONFIG}" + # Update /etc/rc.conf + sed -i '' "s|${_if_epairb}_name|epair${uniq_epair_bridge}b_name|" "${bastille_jail_rc_conf}" + if grep "vnet0" "${bastille_jail_rc_conf}" | grep -q "epair${uniq_epair_bridge}b_name"; then + if [ "${IP}" = "0.0.0.0" ]; then + sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="SYNCDHCP" + else + sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="inet ${IP}" + fi + else + sysrc -f "${bastille_jail_rc_conf}" ifconfig_${_if_vnet}="SYNCDHCP" fi - # Update the exec.* with uniq_epair when cloning jails. - # for VNET jails - sed -i '' "s|bastille\([0-9]\{1,\}\)|${uniq_epair}|g" "${JAIL_CONFIG}" - sed -i '' "s|e\([0-9]\{1,\}\)a_${NEWNAME}|e${uniq_epair_bridge}a_${NEWNAME}|g" "${JAIL_CONFIG}" - sed -i '' "s|e\([0-9]\{1,\}\)b_${NEWNAME}|e${uniq_epair_bridge}b_${NEWNAME}|g" "${JAIL_CONFIG}" - sed -i '' "s|epair\([0-9]\{1,\}\)|epair${uniq_epair_bridge}|g" "${JAIL_CONFIG}" - sed -i '' "s|exec.prestart += \"ifconfig e0a_bastille\([0-9]\{1,\}\).*description.*|exec.prestart += \"ifconfig e0a_${uniq_epair} description \\\\\"vnet host interface for Bastille jail ${NEWNAME}\\\\\"\";|" "${JAIL_CONFIG}" break fi - fi + done + elif echo ${_if} | grep -Eoq 'bastille[0-9]+'; then + # Update VNET config + for _num in $(seq 0 "${bastille_num_range}"); do + if ! grep -oq "bastille${_num}" ${bastille_jailsdir}/*/jail.conf; then + # Update jail.conf epair name + local uniq_epair="bastille${_num}" + local _if_vnet="$(grep ${_if} "${bastille_jail_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" + sed -i '' "s|${_if}|${uniq_epair}|g" "${JAIL_CONFIG}" + # If jail had a static MAC, generate one for clone + if grep -oq ether ${JAIL_CONFIG}; then + local external_interface="$(grep ${uniq_epair} ${JAIL_CONFIG} | grep -o 'addm.*' | awk '{print $3}' | sed 's/["|;]//g')" + generate_static_mac "${NEWNAME}" "${external_interface}" + sed -i '' "s|${uniq_epair} ether.*:.*:.*:.*:.*:.*a\";|${uniq_epair} ether ${macaddr}a\";|" "${JAIL_CONFIG}" + sed -i '' "s|${uniq_epair} ether.*:.*:.*:.*:.*:.*b\";|${uniq_epair} ether ${macaddr}b\";|" "${JAIL_CONFIG}" + fi + sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${JAIL_CONFIG}" + # Update /etc/rc.conf + sed -i '' "s|ifconfig_e0b_${_if}_name|ifconfig_e0b_${uniq_epair}_name|" "${bastille_jail_rc_conf}" + if grep "vnet0" "${bastille_jail_rc_conf}" | grep -q ${uniq_epair}; then + if [ "${IP}" = "0.0.0.0" ]; then + sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="SYNCDHCP" + else + sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0=" inet ${IP} " + fi + else + sysrc -f "${bastille_jail_rc_conf}" ifconfig_${_if_vnet}="SYNCDHCP" + fi + break + fi + done fi done - - # Rename interface to new uniq_epair - sed -i '' "s|ifconfig_e0b_bastille.*_name|ifconfig_e0b_${uniq_epair}_name|" "${bastille_jail_rc_conf}" - sed -i '' "s|ifconfig_e.*b_${TARGET}_name|ifconfig_e${uniq_epair_bridge}b_${NEWNAME}_name|" "${bastille_jail_rc_conf}" - - # If 0.0.0.0 set DHCP, else set static IP address - if [ "${IP}" = "0.0.0.0" ]; then - sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="SYNCDHCP" - else - sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="inet ${IP}" - fi } + update_fstab() { # Update fstab to use the new name FSTAB_CONFIG="${bastille_jailsdir}/${NEWNAME}/fstab" From e36d1c2881d0ccc608e9c0092da214124c0966e3 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 13 Jan 2025 17:19:03 -0700 Subject: [PATCH 064/141] clone: fix mac not applying on bridge --- usr/local/share/bastille/clone.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index 4b01ec10..428bf9c8 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -123,11 +123,11 @@ update_jailconf_vnet() { local _if_vnet="$(grep ${_if_epairb} "${bastille_jail_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" sed -i '' "s|${_if}|epair${uniq_epair_bridge}|g" "${JAIL_CONFIG}" # If jail had a static MAC, generate one for clone - if grep -oq ether ${JAIL_CONFIG}; then + if grep ether ${JAIL_CONFIG} | grep -qoc epair${uniq_epair_bridge}; then local external_interface="$(grep "epair${uniq_epair_bridge}" ${JAIL_CONFIG} | grep -o '[^ ]* addm' | awk '{print $1}')" generate_static_mac "${NEWNAME}" "${external_interface}" - sed -i '' "s|epair${uniq_epair_bridge}a ether.*:.*:.*:.*:.*:.*a\";|epair${uniq_epair}a ether ${macaddr}a\";|" "${JAIL_CONFIG}" - sed -i '' "s|epair${uniq_epair_bridge}b ether.*:.*:.*:.*:.*:.*b\";|epair${uniq_epair}b ether ${macaddr}b\";|" "${JAIL_CONFIG}" + sed -i '' "s|epair${uniq_epair_bridge}a ether.*:.*:.*:.*:.*:.*a\";|epair${uniq_epair_bridge}a ether ${macaddr}a\";|" "${JAIL_CONFIG}" + sed -i '' "s|epair${uniq_epair_bridge}b ether.*:.*:.*:.*:.*:.*b\";|epair${uniq_epair_bridge}b ether ${macaddr}b\";|" "${JAIL_CONFIG}" fi sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${JAIL_CONFIG}" # Update /etc/rc.conf @@ -153,7 +153,7 @@ update_jailconf_vnet() { local _if_vnet="$(grep ${_if} "${bastille_jail_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" sed -i '' "s|${_if}|${uniq_epair}|g" "${JAIL_CONFIG}" # If jail had a static MAC, generate one for clone - if grep -oq ether ${JAIL_CONFIG}; then + if grep ether ${JAIL_CONFIG} | grep -qoc ${uniq_epair}; then local external_interface="$(grep ${uniq_epair} ${JAIL_CONFIG} | grep -o 'addm.*' | awk '{print $3}' | sed 's/["|;]//g')" generate_static_mac "${NEWNAME}" "${external_interface}" sed -i '' "s|${uniq_epair} ether.*:.*:.*:.*:.*:.*a\";|${uniq_epair} ether ${macaddr}a\";|" "${JAIL_CONFIG}" @@ -178,7 +178,6 @@ update_jailconf_vnet() { done } - update_fstab() { # Update fstab to use the new name FSTAB_CONFIG="${bastille_jailsdir}/${NEWNAME}/fstab" From 57a652cc70338bd0c2ecca03812154e94d9605da Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 13 Jan 2025 17:44:30 -0700 Subject: [PATCH 065/141] common: update function to use "epairx" because of name limit in FreeBSD --- usr/local/share/bastille/common.sh | 82 +++++++++++++++++------------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 2b7ea6af..a7b5ed0a 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -123,62 +123,73 @@ generate_static_mac() { } generate_vnet_jail_netblock() { - local jail_name="$1" - local use_unique_bridge="$2" - local external_interface="$3" + local jail_name="${1}" + local use_unique_bridge="${2}" + local external_interface="${3}" local static_mac="${4}" - generate_static_mac "${jail_name}" "${external_interface}" - ## determine number of containers + 1 + ## determine number of interfaces + 1 ## iterate num and grep all jail configs ## define uniq_epair - local jail_list="$(bastille list jails)" - if [ -n "${jail_list}" ]; then - local list_jails_num="$(echo "${jail_list}" | wc -l | awk '{print $1}')" - local num_range=$((list_jails_num + 1)) - for _num in $(seq 0 "${num_range}"); do - if ! grep -q "e[0-9]b_bastille${_num}" "${bastille_jailsdir}"/*/jail.conf; then - if ! grep -q "epair${_num}" "${bastille_jailsdir}"/*/jail.conf; then - local uniq_epair="bastille${_num}" + local _epair_if_count="$(grep -Eos 'epair[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local _bastille_if_count="$(grep -Eos 'bastille[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local epair_num_range=$((_epair_if_count + 1)) + local bastille_num_range=$((_bastille_if_count + 1)) + if [ -n "${use_unique_bridge}" ]; then + if [ "${_epair_if_count}" -gt 0 ]; then + for _num in $(seq 0 "${epair_num_range}"); do + if ! grep -Eosq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then local uniq_epair_bridge="${_num}" break fi - fi - done + done + else + local uniq_epair_bridge="0" + fi else - local uniq_epair="bastille0" - local uniq_epair_bridge="0" + if [ "${_bastille_if_count}" -gt 0 ]; then + for _num in $(seq 0 "${bastille_num_range}"); do + if ! grep -Eosq "bastille${_num}" ${bastille_jailsdir}/*/jail.conf; then + local uniq_epair="bastille${_num}" + break + fi + done + else + local uniq_epair="bastille0" + fi fi + ## If BRIDGE is enabled, generate bridge config, else generate VNET config if [ -n "${use_unique_bridge}" ]; then if [ -n "${static_mac}" ]; then - ## generate bridge config - cat <<-EOF + ## Generate bridged VNET config with static MAC address + generate_static_mac "${jail_name}" "${external_interface}" + cat <<-EOF vnet; - vnet.interface = e${uniq_epair_bridge}b_${jail_name}; + vnet.interface = epair${uniq_epair_bridge}b; exec.prestart += "ifconfig epair${uniq_epair_bridge} create"; exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}a up name e${uniq_epair_bridge}a_${jail_name}"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}b up name e${uniq_epair_bridge}b_${jail_name}"; - exec.prestart += "ifconfig e${uniq_epair_bridge}a_${jail_name} ether ${macaddr}a"; - exec.prestart += "ifconfig e${uniq_epair_bridge}b_${jail_name} ether ${macaddr}b"; - exec.poststop += "ifconfig ${external_interface} deletem e${uniq_epair_bridge}a_${jail_name}"; - exec.poststop += "ifconfig e${uniq_epair_bridge}a_${jail_name} destroy"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}a ether ${macaddr}a"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}b ether ${macaddr}b"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}a description \"vnet host interface for Bastille jail ${jail_name}\""; + exec.poststop += "ifconfig ${external_interface} deletem epair${uniq_epair_bridge}a"; + exec.poststop += "ifconfig epair${uniq_epair_bridge}a destroy"; EOF else - cat <<-EOF + ## Generate bridged VNET config without static MAC address + cat <<-EOF vnet; - vnet.interface = e${uniq_epair_bridge}b_${jail_name}; + vnet.interface = epair${uniq_epair_bridge}b; exec.prestart += "ifconfig epair${uniq_epair_bridge} create"; exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}a up name e${uniq_epair_bridge}a_${jail_name}"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}b up name e${uniq_epair_bridge}b_${jail_name}"; - exec.poststop += "ifconfig ${external_interface} deletem e${uniq_epair_bridge}a_${jail_name}"; - exec.poststop += "ifconfig e${uniq_epair_bridge}a_${jail_name} destroy"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}a description \"vnet host interface for Bastille jail ${jail_name}\""; + exec.poststop += "ifconfig ${external_interface} deletem epair${uniq_epair_bridge}a"; + exec.poststop += "ifconfig epair${uniq_epair_bridge}a destroy"; EOF fi else if [ -n "${static_mac}" ]; then - ## generate config - cat <<-EOF + ## Generate VNET config with static MAC address + generate_static_mac "${jail_name}" "${external_interface}" + cat <<-EOF vnet; vnet.interface = e0b_${uniq_epair}; exec.prestart += "jib addm ${uniq_epair} ${external_interface}"; @@ -188,7 +199,8 @@ EOF exec.poststop += "jib destroy ${uniq_epair}"; EOF else - cat <<-EOF + ## Generate VNET config without static MAC address + cat <<-EOF vnet; vnet.interface = e0b_${uniq_epair}; exec.prestart += "jib addm ${uniq_epair} ${external_interface}"; From 628f0fac34fc2d743a24676a126aaa9131da57ae Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 13 Jan 2025 19:37:59 -0700 Subject: [PATCH 066/141] bastille: move cp to no action commands --- usr/local/bin/bastille | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index 3799429c..a01777e3 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -162,10 +162,10 @@ version|-v|--version) help|-h|--help) usage ;; -bootstrap|create|destroy|export|htop|import|list|mount|rdr|restart|setup|start|top|umount|update|upgrade|verify) +bootstrap|create|cp|destroy|export|htop|import|list|mount|rdr|restart|setup|start|top|umount|update|upgrade|verify) # Nothing "extra" to do for these commands. -- cwells ;; -clone|config|cmd|console|convert|cp|edit|limits|pkg|rcp|rename|service|stop|sysrc|tags|template|zfs) +clone|config|cmd|console|convert|edit|limits|pkg|rcp|rename|service|stop|sysrc|tags|template|zfs) # Parse the target and ensure it exists. -- cwells if [ $# -eq 0 ]; then # No target was given, so show the command's help. -- cwells PARAMS='help' From 1cfbe6b5e01aa8e618a4568156b1b4db06cd4749 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 13 Jan 2025 19:39:34 -0700 Subject: [PATCH 067/141] bastille: remove rcp --- usr/local/bin/bastille | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index a01777e3..14c9d927 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -165,7 +165,7 @@ help|-h|--help) bootstrap|create|cp|destroy|export|htop|import|list|mount|rdr|restart|setup|start|top|umount|update|upgrade|verify) # Nothing "extra" to do for these commands. -- cwells ;; -clone|config|cmd|console|convert|edit|limits|pkg|rcp|rename|service|stop|sysrc|tags|template|zfs) +clone|config|cmd|console|convert|edit|limits|pkg|rename|service|stop|sysrc|tags|template|zfs) # Parse the target and ensure it exists. -- cwells if [ $# -eq 0 ]; then # No target was given, so show the command's help. -- cwells PARAMS='help' From b1a3306cef06eb32f785be7ef1d057f4909e2804 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 14 Jan 2025 07:33:43 -0700 Subject: [PATCH 068/141] common: use FreeBSD prefix for static MAC --- usr/local/share/bastille/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index a7b5ed0a..a71b4182 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -113,7 +113,7 @@ generate_static_mac() { local jail_name="${1}" local external_interface="${2}" local external_interface_mac="$(ifconfig ${external_interface} | grep ether | awk '{print $2}')" - local macaddr_prefix="$(echo ${external_interface_mac} | cut -d':' -f1-3)" + local macaddr_prefix="58:9c:fc" local macaddr_suffix="$(echo -n "${external_interface_mac}${jail_name}" | sed 's#:##g' | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" if [ -z "${macaddr_prefix}" ] || [ -z "${macaddr_suffix}" ]; then error_notify "Failed to generate MAC address." From 9420441a566dd480aac3f80ca5c461017c378e2a Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 14 Jan 2025 10:54:28 -0700 Subject: [PATCH 069/141] common: Add comments about static MAC --- usr/local/share/bastille/common.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index a71b4182..973a37ca 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -113,7 +113,9 @@ generate_static_mac() { local jail_name="${1}" local external_interface="${2}" local external_interface_mac="$(ifconfig ${external_interface} | grep ether | awk '{print $2}')" + # Use the FreeBSD vendor MAC prefix for jail MAC prefix "58:9c:fc" local macaddr_prefix="58:9c:fc" + # Hash interface+jailname for jail MAC suffix local macaddr_suffix="$(echo -n "${external_interface_mac}${jail_name}" | sed 's#:##g' | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" if [ -z "${macaddr_prefix}" ] || [ -z "${macaddr_suffix}" ]; then error_notify "Failed to generate MAC address." From b22d68db13eb4653dd01228ecda0ae5b70a439c2 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 14 Jan 2025 11:24:10 -0700 Subject: [PATCH 070/141] update: set -d and -f for release updates and think jail updates --- usr/local/share/bastille/update.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/update.sh b/usr/local/share/bastille/update.sh index 85d632c0..8ee766fc 100644 --- a/usr/local/share/bastille/update.sh +++ b/usr/local/share/bastille/update.sh @@ -96,6 +96,9 @@ jail_check() { } jail_update() { + local _freebsd_update_conf="${bastille_jailsdir}/${TARGET}/root/etc/freebsd-update.conf" + local _jail_dir="${bastille_jailsdir}/${TARGET}/root" + local _workdir="${bastille_releasesdir}/${TARGET}/root/var/db/freebsd-update" # Update a thick container if [ -d "${bastille_jailsdir}/${TARGET}" ]; then jail_check @@ -103,7 +106,9 @@ jail_update() { if [ -z "${CURRENT_VERSION}" ]; then error_exit "Can't determine '${TARGET}' version." else - env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_jailsdir}/${TARGET}/root" \ + env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${_jail_dir}" \ + -d "${_workdir}" \ + -f "${_freebsd_update_conf}" \ fetch install --currently-running "${CURRENT_VERSION}" fi else @@ -112,6 +117,9 @@ jail_update() { } release_update() { + local _freebsd_update_conf="${bastille_releasesdir}/${TARGET}/etc/freebsd-update.conf" + local _release_dir="${bastille_releasesdir}/${TARGET}" + local _workdir="${bastille_releasesdir}/${TARGET}/var/db/freebsd-update" # Update a release base(affects child containers) if [ -d "${bastille_releasesdir}/${TARGET}" ]; then TARGET_TRIM="${TARGET}" @@ -120,8 +128,12 @@ release_update() { fi env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" \ + -d "${_workdir}" \ + -f "${_freebsd_update_conf}" \ fetch --currently-running "${TARGET_TRIM}" env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" \ + -d "${_workdir}" \ + -f "${_freebsd_update_conf}" \ install --currently-running "${TARGET_TRIM}" else error_exit "${TARGET} not found. See 'bastille bootstrap'." From 2f7120a176355045e37e76784c5f8789c33dd0b4 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 14 Jan 2025 13:02:02 -0700 Subject: [PATCH 071/141] update: add debug, code cleanup --- usr/local/share/bastille/update.sh | 113 +++++++++++++++++------------ 1 file changed, 68 insertions(+), 45 deletions(-) diff --git a/usr/local/share/bastille/update.sh b/usr/local/share/bastille/update.sh index 8ee766fc..f2ab3c61 100644 --- a/usr/local/share/bastille/update.sh +++ b/usr/local/share/bastille/update.sh @@ -34,39 +34,62 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille update [release|container|template] | [force]" -} + error_notify "Usage: bastille update [option(s)] TARGET" + cat << EOF + Options: -# Handle special-case commands first. -case "$1" in -help|-h|--help) - usage - ;; -esac + -a | --auto Auto mode. Start/stop jail(s) if required. + -f | --force Force update a release. + -x | --debug Enable debug mode. + +EOF + exit 1 +} if [ $# -gt 2 ] || [ $# -lt 1 ]; then usage fi -bastille_root_check +# Handle options. +OPTION="" +AUTO=0 +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -a|--auto) + AUTO=1 + shift + ;; + -f|--force) + OPTION="-F" + shift + ;; + -x|--debug) + enable_debug + shift + ;; + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + a) AUTO=1 ;; + f) OPTION="-F" ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" ;; + esac + done + shift + ;; + *) + break + ;; + esac +done TARGET="${1}" -OPTION="${2}" -# Handle options -case "${OPTION}" in - -f|--force) - OPTION="-F" - ;; - *) - OPTION= - ;; -esac - -# Check for unsupported actions -if [ "${TARGET}" = "ALL" ]; then - error_exit "Batch upgrade is unsupported." -fi +bastille_root_check if [ -f "/bin/midnightbsd-version" ]; then echo -e "${COLOR_RED}Not yet supported on MidnightBSD.${COLOR_RESET}" @@ -86,22 +109,25 @@ arch_check() { jail_check() { # Check if the jail is thick and is running - if [ ! "$(/usr/sbin/jls name | awk "/^${TARGET}$/")" ]; then - error_exit "[${TARGET}]: Not started. See 'bastille start ${TARGET}'." - else - if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then - error_exit "${TARGET} is not a thick container." - fi + set_target_single "${TARGET}" + check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then + bastille start "${TARGET}" + else + error_notify "Jail is not running." + error_continue "Use [-a|--auto] to auto-start the jail." + fi + if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then + error_notify "${TARGET} is not a thick container." + error_exit "See 'bastille update RELEASE' to update thin jails." fi } jail_update() { local _freebsd_update_conf="${bastille_jailsdir}/${TARGET}/root/etc/freebsd-update.conf" local _jail_dir="${bastille_jailsdir}/${TARGET}/root" - local _workdir="${bastille_releasesdir}/${TARGET}/root/var/db/freebsd-update" + local _workdir="${bastille_jailsdir}/${TARGET}/root/var/db/freebsd-update" # Update a thick container - if [ -d "${bastille_jailsdir}/${TARGET}" ]; then - jail_check + if [ -d "${bastille_jailsdir}/${TARGET}" ]; then CURRENT_VERSION=$(/usr/sbin/jexec -l "${TARGET}" freebsd-version 2>/dev/null) if [ -z "${CURRENT_VERSION}" ]; then error_exit "Can't determine '${TARGET}' version." @@ -111,32 +137,28 @@ jail_update() { -f "${_freebsd_update_conf}" \ fetch install --currently-running "${CURRENT_VERSION}" fi - else - error_exit "${TARGET} not found. See 'bastille bootstrap'." fi } release_update() { local _freebsd_update_conf="${bastille_releasesdir}/${TARGET}/etc/freebsd-update.conf" local _release_dir="${bastille_releasesdir}/${TARGET}" - local _workdir="${bastille_releasesdir}/${TARGET}/var/db/freebsd-update" # Update a release base(affects child containers) - if [ -d "${bastille_releasesdir}/${TARGET}" ]; then + if [ -d "${_release_dir}" ]; then TARGET_TRIM="${TARGET}" if [ -n "${ARCH_I386}" ]; then TARGET_TRIM=$(echo "${TARGET}" | sed 's/-i386//') fi - env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" \ - -d "${_workdir}" \ + -d "${bastille_releasesdir}/${TARGET}/var/db/freebsd-update" \ -f "${_freebsd_update_conf}" \ fetch --currently-running "${TARGET_TRIM}" env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" \ - -d "${_workdir}" \ + -d "${bastille_releasesdir}/${TARGET}/var/db/freebsd-update" \ -f "${_freebsd_update_conf}" \ install --currently-running "${TARGET_TRIM}" else - error_exit "${TARGET} not found. See 'bastille bootstrap'." + error_exit "${TARGET} not found. See 'bastille bootstrap RELEASE'." fi } @@ -157,10 +179,10 @@ template_update() { templates_update() { # Update all templates _updated_templates=0 - if [ -d "${bastille_templatesdir}" ]; then - # shellcheck disable=SC2045 - for _template_path in $(ls -d "${bastille_templatesdir}"/*/*); do - if [ -d "$_template_path"/.git ]; then + if [ -d ${bastille_templatesdir} ]; then + # shellcheck disable=SC2045 + for _template_path in $(ls -d ${bastille_templatesdir}/*/*); do + if [ -d $_template_path/.git ]; then BASTILLE_TEMPLATE=$(echo "$_template_path" | awk -F / '{ print $(NF-1) "/" $NF }') template_update @@ -186,5 +208,6 @@ elif echo "${TARGET}" | grep -q "[0-9]\{2\}.[0-9]-RELEASE"; then arch_check release_update else + jail_check jail_update fi From 6bddbaab2c72b336ff1f98a6ef5ab7872ec36f12 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 14 Jan 2025 13:03:36 -0700 Subject: [PATCH 072/141] upgrade: deprecate RELEASE upgrade, fix thick/thin jail upgrades --- usr/local/share/bastille/upgrade.sh | 167 ++++++++++++++++------------ 1 file changed, 95 insertions(+), 72 deletions(-) diff --git a/usr/local/share/bastille/upgrade.sh b/usr/local/share/bastille/upgrade.sh index 5aa06905..a1092948 100644 --- a/usr/local/share/bastille/upgrade.sh +++ b/usr/local/share/bastille/upgrade.sh @@ -34,31 +34,64 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille upgrade release newrelease | target newrelease | target install | [force]" + error_notify "Usage: bastille upgrade [option(s)] TARGET [NEWRELEASE|install]" + cat << EOF + Options: + + -a | --auto Auto mode. Start/stop jail(s) if required. + -f | --force Force upgrade a release. + -x | --debug Enable debug mode. + +EOF + exit 1 } -# Handle special-case commands first. -case "$1" in -help|-h|--help) - usage - ;; -esac +# Handle options. +OPTION="" +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -a|--auto) + AUTO=1 + shift + ;; + -f|--force) + OPTION="-F" + shift + ;; + -x|--debug) + enable_debug + shift + ;; + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + a) AUTO=1 ;; + f) OPTION="-F" ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" ;; + esac + done + shift + ;; + *) + break + ;; + esac +done -if [ $# -gt 3 ] || [ $# -lt 2 ]; then +if [ $# -lt 2 ] || [ $# -gt 3 ]; then usage fi +TARGET="${1}" +NEWRELEASE="${2}" + bastille_root_check -TARGET="$1" -NEWRELEASE="$2" -OPTION="$3" - -# Check for unsupported actions -if [ "${TARGET}" = "ALL" ]; then - error_exit "Batch upgrade is unsupported." -fi - +# Check for unsupported actions if [ -f "/bin/midnightbsd-version" ]; then echo -e "${COLOR_RED}Not yet supported on MidnightBSD.${COLOR_RESET}" exit 1 @@ -68,24 +101,14 @@ if freebsd-version | grep -qi HBSD; then error_exit "Not yet supported on HardenedBSD." fi -# Handle options -case "${OPTION}" in - -f|--force) - OPTION="-F" - ;; - *) - OPTION= - ;; -esac - jail_check() { # Check if the jail is thick and is running - if [ ! "$(/usr/sbin/jls name | awk "/^${TARGET}$/")" ]; then - error_exit "[${TARGET}]: Not started. See 'bastille start ${TARGET}'." - else - if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then - error_exit "${TARGET} is not a thick container." - fi + set_target_single "${TARGET}" + check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then + bastille start "${TARGET}" + else + error_notify "Jail is not running." + error_continue "Use [-a|--auto] to auto-start the jail." fi } @@ -96,60 +119,60 @@ release_check() { fi } -release_upgrade() { - # Upgrade a release - if [ -d "${bastille_releasesdir}/${TARGET}" ]; then - release_check - env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" --currently-running "${TARGET}" -r "${NEWRELEASE}" upgrade - echo - echo -e "${COLOR_YELLOW}Please run 'bastille upgrade ${TARGET} install' to finish installing updates.${COLOR_RESET}" - else - error_exit "${TARGET} not found. See 'bastille bootstrap'." - fi -} - jail_upgrade() { - # Upgrade a thick container - if [ -d "${bastille_jailsdir}/${TARGET}" ]; then - jail_check - release_check - CURRENT_VERSION=$(jexec -l ${TARGET} freebsd-version) - env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_jailsdir}/${TARGET}/root" --currently-running "${CURRENT_VERSION}" -r ${NEWRELEASE} upgrade + local _jailname="${1}" + local _oldrelease="$(jexec -l ${TARGET} freebsd-version)" + local _newrelease="${2}" + local _jailpath="${bastille_jailsdir}/${TARGET}/root" + local _workdir="${bastille_jailsdir}/${TARGET}/root/var/db/freebsd-update" + local _freebsd_update_conf="${bastille_jailsdir}/${TARGET}/root/etc/freebsd-update.conf" + + jail_check + release_check + + # Upgrade a thin jail + if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then + local _oldrelease="$(grep osrelease ${bastille_jailsdir}/${TARGET}/jail.conf | awk -F"= " '{print $2}' | sed 's/;//g')" + local _newrelease="${NEWRELEASE}" + sed -i '' "/.bastille/ s|${_oldrelease}|${_newrelease}|g" "${bastille_jailsdir}/${TARGET}/fstab" + sed -i '' "/osrelease/ s|${_oldrelease}|${_newrelease}|g" "${bastille_jailsdir}/${TARGET}/jail.conf" + info "Upgraded ${TARGET}: ${_oldrelease} -> ${_newrelease}" + info "See 'bastille etcupdate TARGET' to update /etc/rc.conf" + else + # Upgrade a thick jail + env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron \ + --currently-running "${_oldrelease}" \ + -b "${_jailpath}" \ + -d "${_workdir}" \ + -f "${_freebsd_update_conf}" \ + -r "${_newrelease}" \ + upgrade + echo echo -e "${COLOR_YELLOW}Please run 'bastille upgrade ${TARGET} install' to finish installing updates.${COLOR_RESET}" - else - error_exit "${TARGET} not found. See 'bastille bootstrap'." fi } jail_updates_install() { + local _jailpath="${bastille_jailsdir}/${TARGET}/root" + local _workdir="${bastille_jailsdir}/${TARGET}/root/var/db/freebsd-update" + local _freebsd_update_conf="${bastille_jailsdir}/${TARGET}/root/etc/freebsd-update.conf" # Finish installing upgrade on a thick container if [ -d "${bastille_jailsdir}/${TARGET}" ]; then jail_check - env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_jailsdir}/${TARGET}/root" install + env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron \ + -b "${_jailpath}" \ + -d "${_workdir}" \ + -f "${_freebsd_update_conf}" \ + install else - error_exit "${TARGET} not found. See 'bastille bootstrap'." - fi -} - -release_updates_install() { - # Finish installing upgrade on a release - if [ -d "${bastille_releasesdir}/${TARGET}" ]; then - env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" install - else - error_exit "${TARGET} not found. See 'bastille bootstrap'." + error_exit "${TARGET} not found. See 'bastille bootstrap RELEASE'." fi } # Check what we should upgrade -if echo "${TARGET}" | grep -q "[0-9]\{2\}.[0-9]-RELEASE"; then - if [ "${NEWRELEASE}" = "install" ]; then - release_updates_install - else - release_upgrade - fi -elif [ "${NEWRELEASE}" = "install" ]; then +if [ "${NEWRELEASE}" = "install" ]; then jail_updates_install else - jail_upgrade + jail_upgrade "${TARGET}" "${NEWRELEASE}" fi From 5394ad8979214786aa2b1579499b517994032187 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 14 Jan 2025 13:22:30 -0700 Subject: [PATCH 073/141] upgrade: Update "osrelease" entry --- usr/local/share/bastille/upgrade.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/upgrade.sh b/usr/local/share/bastille/upgrade.sh index a1092948..74822da3 100644 --- a/usr/local/share/bastille/upgrade.sh +++ b/usr/local/share/bastille/upgrade.sh @@ -134,7 +134,9 @@ jail_upgrade() { if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then local _oldrelease="$(grep osrelease ${bastille_jailsdir}/${TARGET}/jail.conf | awk -F"= " '{print $2}' | sed 's/;//g')" local _newrelease="${NEWRELEASE}" + # Update "osrelease" entry inside jail.conf sed -i '' "/.bastille/ s|${_oldrelease}|${_newrelease}|g" "${bastille_jailsdir}/${TARGET}/fstab" + # Update "fstab" entry sed -i '' "/osrelease/ s|${_oldrelease}|${_newrelease}|g" "${bastille_jailsdir}/${TARGET}/jail.conf" info "Upgraded ${TARGET}: ${_oldrelease} -> ${_newrelease}" info "See 'bastille etcupdate TARGET' to update /etc/rc.conf" @@ -145,9 +147,10 @@ jail_upgrade() { -b "${_jailpath}" \ -d "${_workdir}" \ -f "${_freebsd_update_conf}" \ - -r "${_newrelease}" \ - upgrade - + -r "${_newrelease}" upgrade + + # Update "osrelease" entry inside jail.conf + sed -i '' "/osrelease/ s|${_oldrelease}|${_newrelease}|g" "${bastille_jailsdir}/${TARGET}/jail.conf" echo echo -e "${COLOR_YELLOW}Please run 'bastille upgrade ${TARGET} install' to finish installing updates.${COLOR_RESET}" fi From 59296d60a692f8b6f816d50fbe905a1e9ac594d5 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 14 Jan 2025 13:29:46 -0700 Subject: [PATCH 074/141] console: _jail>TARGET --- usr/local/share/bastille/console.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/console.sh b/usr/local/share/bastille/console.sh index c4fcbfd3..0e7a9eea 100644 --- a/usr/local/share/bastille/console.sh +++ b/usr/local/share/bastille/console.sh @@ -108,7 +108,7 @@ validate_user() { } check_fib() { - fib=$(grep 'exec.fib' "${bastille_jailsdir}/${_jail}/jail.conf" | awk '{print $3}' | sed 's/\;//g') + fib=$(grep 'exec.fib' "${bastille_jailsdir}/${TARGET}/jail.conf" | awk '{print $3}' | sed 's/\;//g') if [ -n "${fib}" ]; then _setfib="setfib -F ${fib}" else From a83772dc2b6a01f5bd0ba052d8587d009e0d0602 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 14 Jan 2025 14:49:07 -0700 Subject: [PATCH 075/141] =?UTF-8?q?list:=20Fix=20=E2=80=9Cgrep:=20no=20suc?= =?UTF-8?q?h=20file=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the issue introduced by the 0.12-2025 release. The problem was the entries were being passed to grep as combined strings because of quotes. Remove the quotes solves the issue. --- usr/local/share/bastille/list.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index 3b1845b7..b15b1ddb 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -64,7 +64,7 @@ list_all(){ MAX_LENGTH_JID=${MAX_LENGTH_JID:-3} MAX_LENGTH_JAIL_IP=$(find ${bastille_jailsdir}/*/jail.conf -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 sed -n "s/^[ ]*ip[4,6].addr[ ]*=[ ]*\(.*\);$/\1 /p" | sed 's/\// /g' | awk '{ print length($1) }' | sort -nr | head -n 1) MAX_LENGTH_JAIL_IP=${MAX_LENGTH_JAIL_IP:-10} - MAX_LENGTH_JAIL_VNET_IP=$(find ${bastille_jailsdir}/*/jail.conf -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -l "vnet;" | grep -h "ifconfig_vnet0=" "$(sed -n "s/\(.*\)jail.conf$/\1root\/etc\/rc.conf/p")" | sed -n "s/^ifconfig_vnet0=\"\(.*\)\"$/\1/p"| sed "s/\// /g" | awk '{ if ($1 ~ /^[inet|inet6]/) print length($2); else print 15 }' | sort -nr | head -n 1) + MAX_LENGTH_JAIL_VNET_IP=$(find ${bastille_jailsdir}/*/jail.conf -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -l "vnet;" | grep -h "ifconfig_vnet0=" $(sed -n "s/\(.*\)jail.conf$/\1root\/etc\/rc.conf/p") | sed -n "s/^ifconfig_vnet0=\"\(.*\)\"$/\1/p"| sed "s/\// /g" | awk '{ if ($1 ~ /^[inet|inet6]/) print length($2); else print 15 }' | sort -nr | head -n 1) MAX_LENGTH_JAIL_VNET_IP=${MAX_LENGTH_JAIL_VNET_IP:-10} if [ "${MAX_LENGTH_JAIL_VNET_IP}" -gt "${MAX_LENGTH_JAIL_IP}" ]; then MAX_LENGTH_JAIL_IP=${MAX_LENGTH_JAIL_VNET_IP}; fi if [ "${MAX_LENGTH_JAIL_IP}" -lt 10 ]; then MAX_LENGTH_JAIL_IP=10; fi @@ -75,11 +75,11 @@ list_all(){ MAX_LENGTH_JAIL_PORTS=${MAX_LENGTH_JAIL_PORTS:-15} if [ "${MAX_LENGTH_JAIL_PORTS}" -lt 15 ]; then MAX_LENGTH_JAIL_PORTS=15; fi if [ "${MAX_LENGTH_JAIL_PORTS}" -gt 30 ]; then MAX_LENGTH_JAIL_PORTS=30; fi - MAX_LENGTH_JAIL_RELEASE=$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/releases/.*/root/.bastille.*nullfs" | grep -hE "^USERLAND_VERSION=" "$(sed -n "s/^\(.*\) \/.*$/\1\/bin\/freebsd-version/p" | awk '!_[$0]++')" | sed "s/[\"\'\^]//g;s/ .*$//g" | sed -n "s/^USERLAND_VERSION=\(.*\)$/\1/p" | awk '{ print length($0) }' | sort -nr | head -n 1) + MAX_LENGTH_JAIL_RELEASE=$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/releases/.*/root/.bastille.*nullfs" | grep -hE "^USERLAND_VERSION=" $(sed -n "s/^\(.*\) \/.*$/\1\/bin\/freebsd-version/p" | awk '!_[$0]++') | sed "s/[\"\'\^]//g;s/ .*$//g" | sed -n "s/^USERLAND_VERSION=\(.*\)$/\1/p" | awk '{ print length($0) }' | sort -nr | head -n 1) MAX_LENGTH_JAIL_RELEASE=${MAX_LENGTH_JAIL_RELEASE:-7} MAX_LENGTH_THICK_JAIL_RELEASE=$(find ${bastille_jailsdir}/*/root/bin/freebsd-version -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -hE "^USERLAND_VERSION=" | sed "s/[\"\'\^]//g;s/ .*$//g" | sed -n "s/^USERLAND_VERSION=\(.*\)$/\1/p" | awk '{ print length($0) }' | sort -nr | head -n 1) MAX_LENGTH_THICK_JAIL_RELEASE=${MAX_LENGTH_THICK_JAIL_RELEASE:-7} - MAX_LENGTH_LINUX_JAIL_RELEASE=$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/jails/.*/root/proc.*linprocfs" | grep -hE "^NAME=|^VERSION_ID=|^VERSION_CODENAME=" "$(sed -n "s/^linprocfs *\(.*\)\/.*$/\1\/etc\/os-release/p")" 2> /dev/null | sed "s/\"//g" | sed "s/ GNU\/Linux//g" | sed "N;N;s/\n/;/g" | sed -n "s/^NAME=\(.*\);VERSION_ID=\(.*\);VERSION_CODENAME=\(.*\)$/\1 \2 (\3)/p" | awk '{ print length($0) }' | sort -nr | head -n 1) + MAX_LENGTH_LINUX_JAIL_RELEASE=$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/jails/.*/root/proc.*linprocfs" | grep -hE "^NAME=|^VERSION_ID=|^VERSION_CODENAME=" $(sed -n "s/^linprocfs *\(.*\)\/.*$/\1\/etc\/os-release/p") 2> /dev/null | sed "s/\"//g" | sed "s/ GNU\/Linux//g" | sed "N;N;s/\n/;/g" | sed -n "s/^NAME=\(.*\);VERSION_ID=\(.*\);VERSION_CODENAME=\(.*\)$/\1 \2 (\3)/p" | awk '{ print length($0) }' | sort -nr | head -n 1) MAX_LENGTH_LINUX_JAIL_RELEASE=${MAX_LENGTH_LINUX_JAIL_RELEASE:-7} if [ "${MAX_LENGTH_THICK_JAIL_RELEASE}" -gt "${MAX_LENGTH_JAIL_RELEASE}" ]; then MAX_LENGTH_JAIL_RELEASE=${MAX_LENGTH_THICK_JAIL_RELEASE}; fi if [ "${MAX_LENGTH_LINUX_JAIL_RELEASE}" -gt "${MAX_LENGTH_JAIL_RELEASE}" ]; then MAX_LENGTH_JAIL_RELEASE=${MAX_LENGTH_LINUX_JAIL_RELEASE}; fi From e07f121bcfb8699121e21fcd9fd0b8ce7f02c6cd Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 14 Jan 2025 14:53:56 -0700 Subject: [PATCH 076/141] =?UTF-8?q?List:=20fix=20=E2=80=9C=E2=80=9D=20for?= =?UTF-8?q?=20shell=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- usr/local/share/bastille/list.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index b15b1ddb..694c511c 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -64,7 +64,7 @@ list_all(){ MAX_LENGTH_JID=${MAX_LENGTH_JID:-3} MAX_LENGTH_JAIL_IP=$(find ${bastille_jailsdir}/*/jail.conf -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 sed -n "s/^[ ]*ip[4,6].addr[ ]*=[ ]*\(.*\);$/\1 /p" | sed 's/\// /g' | awk '{ print length($1) }' | sort -nr | head -n 1) MAX_LENGTH_JAIL_IP=${MAX_LENGTH_JAIL_IP:-10} - MAX_LENGTH_JAIL_VNET_IP=$(find ${bastille_jailsdir}/*/jail.conf -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -l "vnet;" | grep -h "ifconfig_vnet0=" $(sed -n "s/\(.*\)jail.conf$/\1root\/etc\/rc.conf/p") | sed -n "s/^ifconfig_vnet0=\"\(.*\)\"$/\1/p"| sed "s/\// /g" | awk '{ if ($1 ~ /^[inet|inet6]/) print length($2); else print 15 }' | sort -nr | head -n 1) + MAX_LENGTH_JAIL_VNET_IP="$(find ${bastille_jailsdir}/*/jail.conf -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -l "vnet;" | grep -h "ifconfig_vnet0=" $(sed -n "s/\(.*\)jail.conf$/\1root\/etc\/rc.conf/p") | sed -n "s/^ifconfig_vnet0=\"\(.*\)\"$/\1/p"| sed "s/\// /g" | awk '{ if ($1 ~ /^[inet|inet6]/) print length($2); else print 15 }' | sort -nr | head -n 1)" MAX_LENGTH_JAIL_VNET_IP=${MAX_LENGTH_JAIL_VNET_IP:-10} if [ "${MAX_LENGTH_JAIL_VNET_IP}" -gt "${MAX_LENGTH_JAIL_IP}" ]; then MAX_LENGTH_JAIL_IP=${MAX_LENGTH_JAIL_VNET_IP}; fi if [ "${MAX_LENGTH_JAIL_IP}" -lt 10 ]; then MAX_LENGTH_JAIL_IP=10; fi @@ -75,11 +75,11 @@ list_all(){ MAX_LENGTH_JAIL_PORTS=${MAX_LENGTH_JAIL_PORTS:-15} if [ "${MAX_LENGTH_JAIL_PORTS}" -lt 15 ]; then MAX_LENGTH_JAIL_PORTS=15; fi if [ "${MAX_LENGTH_JAIL_PORTS}" -gt 30 ]; then MAX_LENGTH_JAIL_PORTS=30; fi - MAX_LENGTH_JAIL_RELEASE=$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/releases/.*/root/.bastille.*nullfs" | grep -hE "^USERLAND_VERSION=" $(sed -n "s/^\(.*\) \/.*$/\1\/bin\/freebsd-version/p" | awk '!_[$0]++') | sed "s/[\"\'\^]//g;s/ .*$//g" | sed -n "s/^USERLAND_VERSION=\(.*\)$/\1/p" | awk '{ print length($0) }' | sort -nr | head -n 1) + MAX_LENGTH_JAIL_RELEASE="$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/releases/.*/root/.bastille.*nullfs" | grep -hE "^USERLAND_VERSION=" $(sed -n "s/^\(.*\) \/.*$/\1\/bin\/freebsd-version/p" | awk '!_[$0]++') | sed "s/[\"\'\^]//g;s/ .*$//g" | sed -n "s/^USERLAND_VERSION=\(.*\)$/\1/p" | awk '{ print length($0) }' | sort -nr | head -n 1)" MAX_LENGTH_JAIL_RELEASE=${MAX_LENGTH_JAIL_RELEASE:-7} MAX_LENGTH_THICK_JAIL_RELEASE=$(find ${bastille_jailsdir}/*/root/bin/freebsd-version -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -hE "^USERLAND_VERSION=" | sed "s/[\"\'\^]//g;s/ .*$//g" | sed -n "s/^USERLAND_VERSION=\(.*\)$/\1/p" | awk '{ print length($0) }' | sort -nr | head -n 1) MAX_LENGTH_THICK_JAIL_RELEASE=${MAX_LENGTH_THICK_JAIL_RELEASE:-7} - MAX_LENGTH_LINUX_JAIL_RELEASE=$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/jails/.*/root/proc.*linprocfs" | grep -hE "^NAME=|^VERSION_ID=|^VERSION_CODENAME=" $(sed -n "s/^linprocfs *\(.*\)\/.*$/\1\/etc\/os-release/p") 2> /dev/null | sed "s/\"//g" | sed "s/ GNU\/Linux//g" | sed "N;N;s/\n/;/g" | sed -n "s/^NAME=\(.*\);VERSION_ID=\(.*\);VERSION_CODENAME=\(.*\)$/\1 \2 (\3)/p" | awk '{ print length($0) }' | sort -nr | head -n 1) + MAX_LENGTH_LINUX_JAIL_RELEASE="$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/jails/.*/root/proc.*linprocfs" | grep -hE "^NAME=|^VERSION_ID=|^VERSION_CODENAME=" $(sed -n "s/^linprocfs *\(.*\)\/.*$/\1\/etc\/os-release/p") 2> /dev/null | sed "s/\"//g" | sed "s/ GNU\/Linux//g" | sed "N;N;s/\n/;/g" | sed -n "s/^NAME=\(.*\);VERSION_ID=\(.*\);VERSION_CODENAME=\(.*\)$/\1 \2 (\3)/p" | awk '{ print length($0) }' | sort -nr | head -n 1)" MAX_LENGTH_LINUX_JAIL_RELEASE=${MAX_LENGTH_LINUX_JAIL_RELEASE:-7} if [ "${MAX_LENGTH_THICK_JAIL_RELEASE}" -gt "${MAX_LENGTH_JAIL_RELEASE}" ]; then MAX_LENGTH_JAIL_RELEASE=${MAX_LENGTH_THICK_JAIL_RELEASE}; fi if [ "${MAX_LENGTH_LINUX_JAIL_RELEASE}" -gt "${MAX_LENGTH_JAIL_RELEASE}" ]; then MAX_LENGTH_JAIL_RELEASE=${MAX_LENGTH_LINUX_JAIL_RELEASE}; fi From b59f02afa3d37f633e19225562683c0bc46d61e2 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:00:13 -0700 Subject: [PATCH 077/141] list: disable shell check (needed for grep error) --- usr/local/share/bastille/list.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index 694c511c..e53959d0 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -64,6 +64,7 @@ list_all(){ MAX_LENGTH_JID=${MAX_LENGTH_JID:-3} MAX_LENGTH_JAIL_IP=$(find ${bastille_jailsdir}/*/jail.conf -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 sed -n "s/^[ ]*ip[4,6].addr[ ]*=[ ]*\(.*\);$/\1 /p" | sed 's/\// /g' | awk '{ print length($1) }' | sort -nr | head -n 1) MAX_LENGTH_JAIL_IP=${MAX_LENGTH_JAIL_IP:-10} + # shellchech disable=SC2046 MAX_LENGTH_JAIL_VNET_IP="$(find ${bastille_jailsdir}/*/jail.conf -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -l "vnet;" | grep -h "ifconfig_vnet0=" $(sed -n "s/\(.*\)jail.conf$/\1root\/etc\/rc.conf/p") | sed -n "s/^ifconfig_vnet0=\"\(.*\)\"$/\1/p"| sed "s/\// /g" | awk '{ if ($1 ~ /^[inet|inet6]/) print length($2); else print 15 }' | sort -nr | head -n 1)" MAX_LENGTH_JAIL_VNET_IP=${MAX_LENGTH_JAIL_VNET_IP:-10} if [ "${MAX_LENGTH_JAIL_VNET_IP}" -gt "${MAX_LENGTH_JAIL_IP}" ]; then MAX_LENGTH_JAIL_IP=${MAX_LENGTH_JAIL_VNET_IP}; fi @@ -75,10 +76,12 @@ list_all(){ MAX_LENGTH_JAIL_PORTS=${MAX_LENGTH_JAIL_PORTS:-15} if [ "${MAX_LENGTH_JAIL_PORTS}" -lt 15 ]; then MAX_LENGTH_JAIL_PORTS=15; fi if [ "${MAX_LENGTH_JAIL_PORTS}" -gt 30 ]; then MAX_LENGTH_JAIL_PORTS=30; fi + # shellchech disable=SC2046 MAX_LENGTH_JAIL_RELEASE="$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/releases/.*/root/.bastille.*nullfs" | grep -hE "^USERLAND_VERSION=" $(sed -n "s/^\(.*\) \/.*$/\1\/bin\/freebsd-version/p" | awk '!_[$0]++') | sed "s/[\"\'\^]//g;s/ .*$//g" | sed -n "s/^USERLAND_VERSION=\(.*\)$/\1/p" | awk '{ print length($0) }' | sort -nr | head -n 1)" MAX_LENGTH_JAIL_RELEASE=${MAX_LENGTH_JAIL_RELEASE:-7} MAX_LENGTH_THICK_JAIL_RELEASE=$(find ${bastille_jailsdir}/*/root/bin/freebsd-version -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -hE "^USERLAND_VERSION=" | sed "s/[\"\'\^]//g;s/ .*$//g" | sed -n "s/^USERLAND_VERSION=\(.*\)$/\1/p" | awk '{ print length($0) }' | sort -nr | head -n 1) MAX_LENGTH_THICK_JAIL_RELEASE=${MAX_LENGTH_THICK_JAIL_RELEASE:-7} + # shellchech disable=SC2046 MAX_LENGTH_LINUX_JAIL_RELEASE="$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/jails/.*/root/proc.*linprocfs" | grep -hE "^NAME=|^VERSION_ID=|^VERSION_CODENAME=" $(sed -n "s/^linprocfs *\(.*\)\/.*$/\1\/etc\/os-release/p") 2> /dev/null | sed "s/\"//g" | sed "s/ GNU\/Linux//g" | sed "N;N;s/\n/;/g" | sed -n "s/^NAME=\(.*\);VERSION_ID=\(.*\);VERSION_CODENAME=\(.*\)$/\1 \2 (\3)/p" | awk '{ print length($0) }' | sort -nr | head -n 1)" MAX_LENGTH_LINUX_JAIL_RELEASE=${MAX_LENGTH_LINUX_JAIL_RELEASE:-7} if [ "${MAX_LENGTH_THICK_JAIL_RELEASE}" -gt "${MAX_LENGTH_JAIL_RELEASE}" ]; then MAX_LENGTH_JAIL_RELEASE=${MAX_LENGTH_THICK_JAIL_RELEASE}; fi From 43dfd98af5072860f654a6209e6a829babca0752 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:02:17 -0700 Subject: [PATCH 078/141] list: typo in shellcheck --- usr/local/share/bastille/list.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index e53959d0..23f13d07 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -64,7 +64,7 @@ list_all(){ MAX_LENGTH_JID=${MAX_LENGTH_JID:-3} MAX_LENGTH_JAIL_IP=$(find ${bastille_jailsdir}/*/jail.conf -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 sed -n "s/^[ ]*ip[4,6].addr[ ]*=[ ]*\(.*\);$/\1 /p" | sed 's/\// /g' | awk '{ print length($1) }' | sort -nr | head -n 1) MAX_LENGTH_JAIL_IP=${MAX_LENGTH_JAIL_IP:-10} - # shellchech disable=SC2046 + # shellcheck disable=SC2046 MAX_LENGTH_JAIL_VNET_IP="$(find ${bastille_jailsdir}/*/jail.conf -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -l "vnet;" | grep -h "ifconfig_vnet0=" $(sed -n "s/\(.*\)jail.conf$/\1root\/etc\/rc.conf/p") | sed -n "s/^ifconfig_vnet0=\"\(.*\)\"$/\1/p"| sed "s/\// /g" | awk '{ if ($1 ~ /^[inet|inet6]/) print length($2); else print 15 }' | sort -nr | head -n 1)" MAX_LENGTH_JAIL_VNET_IP=${MAX_LENGTH_JAIL_VNET_IP:-10} if [ "${MAX_LENGTH_JAIL_VNET_IP}" -gt "${MAX_LENGTH_JAIL_IP}" ]; then MAX_LENGTH_JAIL_IP=${MAX_LENGTH_JAIL_VNET_IP}; fi @@ -76,12 +76,12 @@ list_all(){ MAX_LENGTH_JAIL_PORTS=${MAX_LENGTH_JAIL_PORTS:-15} if [ "${MAX_LENGTH_JAIL_PORTS}" -lt 15 ]; then MAX_LENGTH_JAIL_PORTS=15; fi if [ "${MAX_LENGTH_JAIL_PORTS}" -gt 30 ]; then MAX_LENGTH_JAIL_PORTS=30; fi - # shellchech disable=SC2046 + # shellcheck disable=SC2046 MAX_LENGTH_JAIL_RELEASE="$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/releases/.*/root/.bastille.*nullfs" | grep -hE "^USERLAND_VERSION=" $(sed -n "s/^\(.*\) \/.*$/\1\/bin\/freebsd-version/p" | awk '!_[$0]++') | sed "s/[\"\'\^]//g;s/ .*$//g" | sed -n "s/^USERLAND_VERSION=\(.*\)$/\1/p" | awk '{ print length($0) }' | sort -nr | head -n 1)" MAX_LENGTH_JAIL_RELEASE=${MAX_LENGTH_JAIL_RELEASE:-7} MAX_LENGTH_THICK_JAIL_RELEASE=$(find ${bastille_jailsdir}/*/root/bin/freebsd-version -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -hE "^USERLAND_VERSION=" | sed "s/[\"\'\^]//g;s/ .*$//g" | sed -n "s/^USERLAND_VERSION=\(.*\)$/\1/p" | awk '{ print length($0) }' | sort -nr | head -n 1) MAX_LENGTH_THICK_JAIL_RELEASE=${MAX_LENGTH_THICK_JAIL_RELEASE:-7} - # shellchech disable=SC2046 + # shellcheck disable=SC2046 MAX_LENGTH_LINUX_JAIL_RELEASE="$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/jails/.*/root/proc.*linprocfs" | grep -hE "^NAME=|^VERSION_ID=|^VERSION_CODENAME=" $(sed -n "s/^linprocfs *\(.*\)\/.*$/\1\/etc\/os-release/p") 2> /dev/null | sed "s/\"//g" | sed "s/ GNU\/Linux//g" | sed "N;N;s/\n/;/g" | sed -n "s/^NAME=\(.*\);VERSION_ID=\(.*\);VERSION_CODENAME=\(.*\)$/\1 \2 (\3)/p" | awk '{ print length($0) }' | sort -nr | head -n 1)" MAX_LENGTH_LINUX_JAIL_RELEASE=${MAX_LENGTH_LINUX_JAIL_RELEASE:-7} if [ "${MAX_LENGTH_THICK_JAIL_RELEASE}" -gt "${MAX_LENGTH_JAIL_RELEASE}" ]; then MAX_LENGTH_JAIL_RELEASE=${MAX_LENGTH_THICK_JAIL_RELEASE}; fi From edc6f29184100167d558cbea87f6e34d4adb2392 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 15 Jan 2025 14:33:22 -0700 Subject: [PATCH 079/141] common: final revision of changes --- usr/local/share/bastille/common.sh | 109 ++++++++++++++++++----------- 1 file changed, 67 insertions(+), 42 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 3e29683c..5c84495f 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -1,6 +1,8 @@ #!/bin/sh # -# Copyright (c) 2018-2024, Christer Edwards +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright (c) 2018-2025, Christer Edwards # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -209,61 +211,74 @@ target_all_jails() { export JAILS } -generate_static_mac() { - local jail_name="${1}" - local external_interface="${2}" - local external_interface_mac="$(ifconfig ${external_interface} | grep ether | awk '{print $2}' | sed 's#:##g')" - local macaddr_prefix="$(echo -n "${external_interface_mac}" | sha256 | cut -b -6 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" - local macaddr_suffix="$(echo -n "${jail_name}" | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" - if [ -z "${macaddr_prefix}" ] || [ -z "${macaddr_suffix}" ]; then - error_notify "Failed to generate MAC address." - fi - macaddr="${macaddr_prefix}:${macaddr_suffix}" - export macaddr -} - generate_vnet_jail_netblock() { - local jail_name="$1" - local use_unique_bridge="$2" - local external_interface="$3" - generate_static_mac "${jail_name}" "${external_interface}" - ## determine number of containers + 1 + local jail_name="${1}" + local use_unique_bridge="${2}" + local external_interface="${3}" + local static_mac="${4}" + ## determine number of interfaces + 1 ## iterate num and grep all jail configs ## define uniq_epair - local jail_list="$(bastille list jails)" - if [ -n "${jail_list}" ]; then - local list_jails_num="$(echo "${jail_list}" | wc -l | awk '{print $1}')" - local num_range=$((list_jails_num + 1)) - for _num in $(seq 0 "${num_range}"); do - if ! grep -q "e[0-9]b_bastille${_num}" "${bastille_jailsdir}"/*/jail.conf; then - if ! grep -q "epair${_num}" "${bastille_jailsdir}"/*/jail.conf; then - local uniq_epair="bastille${_num}" + local _epair_if_count="$(grep -Eos 'epair[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local _vnet_if_count="$(grep -Eos 'bastille[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local epair_num_range=$((_epair_if_count + 1)) + local vnet_num_range=$((_vnet_if_count + 1)) + if [ -n "${use_unique_bridge}" ]; then + if [ "${_epair_if_count}" -gt 0 ]; then + for _num in $(seq 0 "${epair_num_range}"); do + if ! grep -Eosq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then local uniq_epair_bridge="${_num}" break fi - fi - done + done + else + local uniq_epair_bridge="0" + fi else - local uniq_epair="bastille0" - local uniq_epair_bridge="0" + if [ "${_vnet_if_count}" -gt 0 ]; then + for _num in $(seq 0 "${vnet_num_range}"); do + if ! grep -Eosq "bastille${_num}" ${bastille_jailsdir}/*/jail.conf; then + local uniq_epair="bastille${_num}" + break + fi + done + else + local uniq_epair="bastille0" + fi fi + ## If BRIDGE is enabled, generate bridge config, else generate VNET config if [ -n "${use_unique_bridge}" ]; then - ## generate bridge config - cat <<-EOF + if [ -n "${static_mac}" ]; then + ## Generate bridged VNET config with static MAC address + generate_static_mac "${jail_name}" "${external_interface}" + cat <<-EOF vnet; - vnet.interface = e${uniq_epair_bridge}b_${jail_name}; + vnet.interface = epair${uniq_epair_bridge}b; exec.prestart += "ifconfig epair${uniq_epair_bridge} create"; exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}a up name e${uniq_epair_bridge}a_${jail_name}"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}b up name e${uniq_epair_bridge}b_${jail_name}"; - exec.prestart += "ifconfig e${uniq_epair_bridge}a_${jail_name} ether ${macaddr}a"; - exec.prestart += "ifconfig e${uniq_epair_bridge}b_${jail_name} ether ${macaddr}b"; - exec.poststop += "ifconfig ${external_interface} deletem e${uniq_epair_bridge}a_${jail_name}"; - exec.poststop += "ifconfig e${uniq_epair_bridge}a_${jail_name} destroy"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}a ether ${macaddr}a"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}b ether ${macaddr}b"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}a description \"vnet host interface for Bastille jail ${jail_name}\""; + exec.poststop += "ifconfig ${external_interface} deletem epair${uniq_epair_bridge}a"; + exec.poststop += "ifconfig epair${uniq_epair_bridge}a destroy"; EOF + else + ## Generate bridged VNET config without static MAC address + cat <<-EOF + vnet; + vnet.interface = epair${uniq_epair_bridge}b; + exec.prestart += "ifconfig epair${uniq_epair_bridge} create"; + exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a"; + exec.prestart += "ifconfig epair${uniq_epair_bridge}a description \"vnet host interface for Bastille jail ${jail_name}\""; + exec.poststop += "ifconfig ${external_interface} deletem epair${uniq_epair_bridge}a"; + exec.poststop += "ifconfig epair${uniq_epair_bridge}a destroy"; +EOF + fi else - ## generate config - cat <<-EOF + if [ -n "${static_mac}" ]; then + ## Generate VNET config with static MAC address + generate_static_mac "${jail_name}" "${external_interface}" + cat <<-EOF vnet; vnet.interface = e0b_${uniq_epair}; exec.prestart += "jib addm ${uniq_epair} ${external_interface}"; @@ -272,6 +287,16 @@ EOF exec.prestart += "ifconfig e0a_${uniq_epair} description \"vnet host interface for Bastille jail ${jail_name}\""; exec.poststop += "jib destroy ${uniq_epair}"; EOF + else + ## Generate VNET config without static MAC address + cat <<-EOF + vnet; + vnet.interface = e0b_${uniq_epair}; + exec.prestart += "jib addm ${uniq_epair} ${external_interface}"; + exec.prestart += "ifconfig e0a_${uniq_epair} description \"vnet host interface for Bastille jail ${jail_name}\""; + exec.poststop += "jib destroy ${uniq_epair}"; +EOF + fi fi } From 35f698bc960d97d0c598c6f38e4316772f3d3359 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 16 Jan 2025 07:25:49 -0700 Subject: [PATCH 080/141] upgrade: use $jailpath for vars --- usr/local/share/bastille/upgrade.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/usr/local/share/bastille/upgrade.sh b/usr/local/share/bastille/upgrade.sh index 74822da3..0b9d2365 100644 --- a/usr/local/share/bastille/upgrade.sh +++ b/usr/local/share/bastille/upgrade.sh @@ -124,8 +124,8 @@ jail_upgrade() { local _oldrelease="$(jexec -l ${TARGET} freebsd-version)" local _newrelease="${2}" local _jailpath="${bastille_jailsdir}/${TARGET}/root" - local _workdir="${bastille_jailsdir}/${TARGET}/root/var/db/freebsd-update" - local _freebsd_update_conf="${bastille_jailsdir}/${TARGET}/root/etc/freebsd-update.conf" + local _workdir="${_jailpath}/var/db/freebsd-update" + local _freebsd_update_conf="${_jailpath}/etc/freebsd-update.conf" jail_check release_check @@ -158,8 +158,8 @@ jail_upgrade() { jail_updates_install() { local _jailpath="${bastille_jailsdir}/${TARGET}/root" - local _workdir="${bastille_jailsdir}/${TARGET}/root/var/db/freebsd-update" - local _freebsd_update_conf="${bastille_jailsdir}/${TARGET}/root/etc/freebsd-update.conf" + local _workdir="${_jailpath}/var/db/freebsd-update" + local _freebsd_update_conf="${_jailpath}/etc/freebsd-update.conf" # Finish installing upgrade on a thick container if [ -d "${bastille_jailsdir}/${TARGET}" ]; then jail_check From e4f58af7707eb18211416c613623763eac1b4377 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 16 Jan 2025 07:27:48 -0700 Subject: [PATCH 081/141] upgrade: Use -j jailname instead of -b --- usr/local/share/bastille/upgrade.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/upgrade.sh b/usr/local/share/bastille/upgrade.sh index 0b9d2365..70db6071 100644 --- a/usr/local/share/bastille/upgrade.sh +++ b/usr/local/share/bastille/upgrade.sh @@ -144,7 +144,7 @@ jail_upgrade() { # Upgrade a thick jail env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron \ --currently-running "${_oldrelease}" \ - -b "${_jailpath}" \ + -j "${_jailname}" \ -d "${_workdir}" \ -f "${_freebsd_update_conf}" \ -r "${_newrelease}" upgrade @@ -164,7 +164,7 @@ jail_updates_install() { if [ -d "${bastille_jailsdir}/${TARGET}" ]; then jail_check env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron \ - -b "${_jailpath}" \ + -j "${_jailname}" \ -d "${_workdir}" \ -f "${_freebsd_update_conf}" \ install From a74f87162ae27b7e417d2df99f347df28a2e390f Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Thu, 16 Jan 2025 07:36:25 -0700 Subject: [PATCH 082/141] update: Use -j jailpath and _release path as vars --- usr/local/share/bastille/update.sh | 33 ++++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/usr/local/share/bastille/update.sh b/usr/local/share/bastille/update.sh index f2ab3c61..f1ee3ef7 100644 --- a/usr/local/share/bastille/update.sh +++ b/usr/local/share/bastille/update.sh @@ -123,38 +123,45 @@ jail_check() { } jail_update() { - local _freebsd_update_conf="${bastille_jailsdir}/${TARGET}/root/etc/freebsd-update.conf" - local _jail_dir="${bastille_jailsdir}/${TARGET}/root" - local _workdir="${bastille_jailsdir}/${TARGET}/root/var/db/freebsd-update" + local _jailname="${1}" + local _jailpath="${bastille_jailsdir}/${TARGET}/root" + local _freebsd_update_conf="${_jailpath}/etc/freebsd-update.conf" + local _workdir="${_jailpath}/var/db/freebsd-update" # Update a thick container if [ -d "${bastille_jailsdir}/${TARGET}" ]; then CURRENT_VERSION=$(/usr/sbin/jexec -l "${TARGET}" freebsd-version 2>/dev/null) if [ -z "${CURRENT_VERSION}" ]; then error_exit "Can't determine '${TARGET}' version." else - env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${_jail_dir}" \ + env PAGER="/bin/cat" freebsd-update ${OPTION} \ + --not-running-from-cron \ + -j "${_jailname}" \ -d "${_workdir}" \ -f "${_freebsd_update_conf}" \ - fetch install --currently-running "${CURRENT_VERSION}" + fetch install fi fi } release_update() { - local _freebsd_update_conf="${bastille_releasesdir}/${TARGET}/etc/freebsd-update.conf" - local _release_dir="${bastille_releasesdir}/${TARGET}" + local _releasepath="${bastille_releasesdir}/${TARGET}" + local _freebsd_update_conf="${_releasepath}/etc/freebsd-update.conf" # Update a release base(affects child containers) - if [ -d "${_release_dir}" ]; then + if [ -d "${_releasepath}" ]; then TARGET_TRIM="${TARGET}" if [ -n "${ARCH_I386}" ]; then TARGET_TRIM=$(echo "${TARGET}" | sed 's/-i386//') fi - env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" \ - -d "${bastille_releasesdir}/${TARGET}/var/db/freebsd-update" \ + env PAGER="/bin/cat" freebsd-update ${OPTION} \ + --not-running-from-cron \ + -b "${_releasepath}" \ + -d "${_releasepath}/var/db/freebsd-update" \ -f "${_freebsd_update_conf}" \ fetch --currently-running "${TARGET_TRIM}" - env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" \ - -d "${bastille_releasesdir}/${TARGET}/var/db/freebsd-update" \ + env PAGER="/bin/cat" freebsd-update ${OPTION} \ + --not-running-from-cron \ + -b "${_releasepath}" \ + -d "${_releasepath}/var/db/freebsd-update" \ -f "${_freebsd_update_conf}" \ install --currently-running "${TARGET_TRIM}" else @@ -209,5 +216,5 @@ elif echo "${TARGET}" | grep -q "[0-9]\{2\}.[0-9]-RELEASE"; then release_update else jail_check - jail_update + jail_update "${TARGET}" fi From ce0ab9d3642e8513a60f62ef0e3664d8a5e88d2f Mon Sep 17 00:00:00 2001 From: Matthias Petermann Date: Fri, 17 Jan 2025 09:58:23 +0100 Subject: [PATCH 083/141] Commit fb71f0d introduced to possibility to add options behind permissions in fstab. Unfortunately it breaks scenarios where no options are provided as the current regex expects the comma with the options always to be present. This patch fixes the regex to handle the options as group. --- usr/local/share/bastille/mount.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index b2aeb438..8aa3cb78 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -92,7 +92,7 @@ elif [ ! -e "${_hostpath}" ] || [ "${_type}" != "nullfs" ]; then fi # Mount permissions,options need to start with "ro" or "rw" -if ! echo "${_perms}" | grep -Eq 'r[w|o],.*$'; then +if ! echo "${_perms}" | grep -Eq 'r[w|o](,.*)?$'; then error_notify "Detected invalid mount permissions in FSTAB." warn "Format: /host/path /jail/path nullfs ro 0 0" warn "Read: ${_fstab}" From 6eaa16e2998d77456ee41c60717fb5576778f515 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 17 Jan 2025 07:34:13 -0700 Subject: [PATCH 084/141] =?UTF-8?q?update:=20use=20=E2=80=9Cworkdir?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- usr/local/share/bastille/update.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/update.sh b/usr/local/share/bastille/update.sh index f1ee3ef7..1a387b36 100644 --- a/usr/local/share/bastille/update.sh +++ b/usr/local/share/bastille/update.sh @@ -146,6 +146,7 @@ jail_update() { release_update() { local _releasepath="${bastille_releasesdir}/${TARGET}" local _freebsd_update_conf="${_releasepath}/etc/freebsd-update.conf" + local _workdir="${_releasepath}/var/db/freebsd-update" # Update a release base(affects child containers) if [ -d "${_releasepath}" ]; then TARGET_TRIM="${TARGET}" @@ -155,13 +156,13 @@ release_update() { env PAGER="/bin/cat" freebsd-update ${OPTION} \ --not-running-from-cron \ -b "${_releasepath}" \ - -d "${_releasepath}/var/db/freebsd-update" \ + -d "${_workdir}" \ -f "${_freebsd_update_conf}" \ fetch --currently-running "${TARGET_TRIM}" env PAGER="/bin/cat" freebsd-update ${OPTION} \ --not-running-from-cron \ -b "${_releasepath}" \ - -d "${_releasepath}/var/db/freebsd-update" \ + -d "${_workdir}" \ -f "${_freebsd_update_conf}" \ install --currently-running "${TARGET_TRIM}" else From ee0b8b8f962bd44ca4f8ae3554cef53665b56928 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 17 Jan 2025 08:11:58 -0700 Subject: [PATCH 085/141] mount: fix perms check --- usr/local/share/bastille/mount.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index c6bf5bf8..604a70d7 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -89,8 +89,8 @@ elif [ ! -e "${_hostpath}" ] || [ "${_type}" != "nullfs" ]; then usage fi -# Mount permissions,options need to include at least one of "ro, rw, rq, sw, xx" -if ! echo "${_perms}" | grep -Eq '[ro|rw|rq|sw|xx]'; then +# Mount permissions,options must start with one of "ro, rw, rq, sw, xx" +if ! echo "${_perms}" | grep -Eq '(ro|rw|rq|sw|xx)(,.*)?$'; then error_notify "Detected invalid mount permissions in FSTAB." warn "Format: /host/path /jail/path nullfs ro 0 0" warn "Read: ${_fstab}" From d9106b5b3ebd2ebb690ec8898ab1eb8c30c0f8c3 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 17 Jan 2025 08:13:29 -0700 Subject: [PATCH 086/141] docs: Fix mount perms check docs --- docs/chapters/subcommands/mount.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/chapters/subcommands/mount.rst b/docs/chapters/subcommands/mount.rst index a5fbc930..172799ad 100644 --- a/docs/chapters/subcommands/mount.rst +++ b/docs/chapters/subcommands/mount.rst @@ -10,7 +10,7 @@ Syntax follows standard `/etc/fstab` format: Usage: bastille mount TARGET HOST_PATH JAIL_PATH [filesystem_type options dump pass_number] -The 'options' string can include a comma-separated list of mount options, but must include at least one of (rw,ro,rq,sw,xx) according to fstab documentation. +The 'options' string can include a comma-separated list of mount options, but must start with one of (rw,ro,rq,sw,xx) according to fstab documentation. Example: Mount a tmpfs filesystem with options. .. code-block:: shell From 5cfbe222adff6789d4d1ae1c43d8ec3daeafa22d Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 17 Jan 2025 12:27:11 -0700 Subject: [PATCH 087/141] upgrade: Fix jail update var --- usr/local/share/bastille/upgrade.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/upgrade.sh b/usr/local/share/bastille/upgrade.sh index 70db6071..2be09435 100644 --- a/usr/local/share/bastille/upgrade.sh +++ b/usr/local/share/bastille/upgrade.sh @@ -157,6 +157,7 @@ jail_upgrade() { } jail_updates_install() { + local _jailname="${1}" local _jailpath="${bastille_jailsdir}/${TARGET}/root" local _workdir="${_jailpath}/var/db/freebsd-update" local _freebsd_update_conf="${_jailpath}/etc/freebsd-update.conf" @@ -175,7 +176,7 @@ jail_updates_install() { # Check what we should upgrade if [ "${NEWRELEASE}" = "install" ]; then - jail_updates_install + jail_updates_install "${TARGET}" else jail_upgrade "${TARGET}" "${NEWRELEASE}" fi From bbb1555eccc148e8353e347ce418d9254cb1b2c0 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 18 Jan 2025 07:33:00 -0700 Subject: [PATCH 088/141] mount: Fix similar path mount grep --- usr/local/share/bastille/mount.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index 1c2a8efb..5895823a 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -117,7 +117,7 @@ for _jail in ${JAILS}; do # Check if mount point has already been added _existing_mount="$(echo ${_fullpath_fstab} 2>/dev/null | sed 's#\\#\\\\#g')" - if grep -Eq "[[:blank:]]${_existing_mount}.*[[:blank:]]" "${bastille_jailsdir}/${_jail}/fstab"; then + if grep -Eq "[[:blank:]]${_existing_mount}[[:blank:]]" "${bastille_jailsdir}/${_jail}/fstab"; then warn "Mountpoint already present in ${bastille_jailsdir}/${_jail}/fstab" grep -E "[[:blank:]]${_existing_mount}" "${bastille_jailsdir}/${_jail}/fstab" continue From e1a2ed1b6bf9ea5d849d219fefa7acb73da92c3a Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 18 Jan 2025 07:39:42 -0700 Subject: [PATCH 089/141] mount: Fix () > [] --- usr/local/share/bastille/mount.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index 5895823a..398d1bf8 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -92,7 +92,7 @@ elif [ ! -e "${_hostpath}" ] || [ "${_type}" != "nullfs" ]; then fi # Mount permissions,options must start with one of "ro, rw, rq, sw, xx" -if ! echo "${_perms}" | grep -Eq '(ro|rw|rq|sw|xx)(,.*)?$'; then +if ! echo "${_perms}" | grep -Eq '[ro|rw|rq|sw|xx](,.*)?$'; then error_notify "Detected invalid mount permissions in FSTAB." warn "Format: /host/path /jail/path nullfs ro 0 0" warn "Read: ${_fstab}" From f994df3baddae8a4c68ad9464a750facfa2b62cc Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 18 Jan 2025 07:51:00 -0700 Subject: [PATCH 090/141] mount: Revert [] > () --- usr/local/share/bastille/mount.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index 398d1bf8..5895823a 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -92,7 +92,7 @@ elif [ ! -e "${_hostpath}" ] || [ "${_type}" != "nullfs" ]; then fi # Mount permissions,options must start with one of "ro, rw, rq, sw, xx" -if ! echo "${_perms}" | grep -Eq '[ro|rw|rq|sw|xx](,.*)?$'; then +if ! echo "${_perms}" | grep -Eq '(ro|rw|rq|sw|xx)(,.*)?$'; then error_notify "Detected invalid mount permissions in FSTAB." warn "Format: /host/path /jail/path nullfs ro 0 0" warn "Read: ${_fstab}" From fdff42a1b3f2709251d004e88be35d4877cc80d7 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 18 Jan 2025 10:08:02 -0700 Subject: [PATCH 091/141] common: fix epair naming --- usr/local/share/bastille/common.sh | 98 ++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 27 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 5c84495f..7db2baf6 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -30,7 +30,10 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -. /usr/local/etc/bastille/bastille.conf +# Source config file +if [ -f /usr/local/etc/bastille/bastille.conf ]; then + . /usr/local/etc/bastille/bastille.conf +fi COLOR_RED= COLOR_GREEN= @@ -90,7 +93,7 @@ warn() { check_target_exists() { local _TARGET="${1}" local _jaillist="$(bastille list jails)" - if ! echo "${_jaillist}" | grep -Eoq "^${_TARGET}$"; then + if ! echo "${_jaillist}" | grep -Eq "^${_TARGET}$"; then return 1 else return 0 @@ -99,7 +102,7 @@ check_target_exists() { check_target_is_running() { local _TARGET="${1}" - if ! jls name | grep -Eoq "^${_TARGET}$"; then + if ! jls name | grep -Eq "^${_TARGET}$"; then return 1 else return 0 @@ -108,7 +111,7 @@ check_target_is_running() { check_target_is_stopped() { local _TARGET="${1}" - if jls name | grep -Eoq "^${_TARGET}$"; then + if jls name | grep -Eq "^${_TARGET}$"; then return 1 else return 0 @@ -184,8 +187,7 @@ set_target_single() { else error_exit "Error: JID \"${_TARGET}\" not found. Is jail running?" fi - elif - ! check_target_exists "${_TARGET}"; then + elif ! check_target_exists "${_TARGET}"; then if jail_autocomplete "${_TARGET}" > /dev/null; then _TARGET="$(jail_autocomplete ${_TARGET})" elif [ $? -eq 2 ]; then @@ -211,6 +213,30 @@ target_all_jails() { export JAILS } +update_fstab() { + local _oldname="${1}" + local _newname="${2}" + local _fstab="${bastille_jailsdir}/${_newname}/fstab" + if [ -f "${_fstab}" ]; then + sed -i '' "s|${bastille_jailsdir}/${_oldname}/root/|${bastille_jailsdir}/${_newname}/root/|" "${_fstab}" + else + error_notify "Error: Failed to update fstab: ${_newmane}" + fi +} + +generate_static_mac() { + local jail_name="${1}" + local external_interface="${2}" + local external_interface_mac="$(ifconfig ${external_interface} | grep ether | awk '{print $2}')" + local macaddr_prefix="58:9c:fc" + local macaddr_suffix="$(echo -n "${external_interface_mac}${jail_name}" | sed 's#:##g' | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" + if [ -z "${macaddr_prefix}" ] || [ -z "${macaddr_suffix}" ]; then + error_notify "Failed to generate MAC address." + fi + macaddr="${macaddr_prefix}:${macaddr_suffix}" + export macaddr +} + generate_vnet_jail_netblock() { local jail_name="${1}" local use_unique_bridge="${2}" @@ -220,23 +246,37 @@ generate_vnet_jail_netblock() { ## iterate num and grep all jail configs ## define uniq_epair local _epair_if_count="$(grep -Eos 'epair[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" - local _vnet_if_count="$(grep -Eos 'bastille[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local _bastille_if_count="$(grep -Eos 'bastille[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" local epair_num_range=$((_epair_if_count + 1)) - local vnet_num_range=$((_vnet_if_count + 1)) + local bastille_num_range=$((_bastille_if_count + 1)) if [ -n "${use_unique_bridge}" ]; then if [ "${_epair_if_count}" -gt 0 ]; then for _num in $(seq 0 "${epair_num_range}"); do if ! grep -Eosq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then - local uniq_epair_bridge="${_num}" + if [ "$(echo -n "e${_num}a_${jail_name}" | awk '{print length}')" -lt 16 ]; then + local host_epair=e${_num}a_${jail_name} + local jail_epair=e${_num}b_${jail_name} + else + local host_epair=epair${_num}a + local jail_epair=epair${_num}b + fi break fi done else - local uniq_epair_bridge="0" + if [ "$(echo -n "e0a_${jail_name}" | awk '{print length}')" -lt 16 ]; then + local _num=0 + local host_epair=e${_num}a_${jail_name} + local jail_epair=e${_num}b_${jail_name} + else + local _num=0 + local host_epair=epair${_num}a + local jail_epair=epair${_num}b + fi fi else - if [ "${_vnet_if_count}" -gt 0 ]; then - for _num in $(seq 0 "${vnet_num_range}"); do + if [ "${_bastille_if_count}" -gt 0 ]; then + for _num in $(seq 0 "${bastille_num_range}"); do if ! grep -Eosq "bastille${_num}" ${bastille_jailsdir}/*/jail.conf; then local uniq_epair="bastille${_num}" break @@ -253,25 +293,29 @@ generate_vnet_jail_netblock() { generate_static_mac "${jail_name}" "${external_interface}" cat <<-EOF vnet; - vnet.interface = epair${uniq_epair_bridge}b; - exec.prestart += "ifconfig epair${uniq_epair_bridge} create"; - exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}a ether ${macaddr}a"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}b ether ${macaddr}b"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}a description \"vnet host interface for Bastille jail ${jail_name}\""; - exec.poststop += "ifconfig ${external_interface} deletem epair${uniq_epair_bridge}a"; - exec.poststop += "ifconfig epair${uniq_epair_bridge}a destroy"; + vnet.interface = ${jail_epair}; + exec.prestart += "ifconfig epair${_num} create"; + exec.prestart += "ifconfig ${external_interface} addm epair${_num}a"; + exec.prestart += "ifconfig epair${_num}a up name ${host_epair}"; + exec.prestart += "ifconfig epair${_num}b up name ${jail_epair}"; + exec.prestart += "ifconfig ${host_epair} ether ${macaddr}a"; + exec.prestart += "ifconfig ${jail_epair} ether ${macaddr}b"; + exec.prestart += "ifconfig ${host_epair} description \"vnet host interface for Bastille jail ${jail_name}\""; + exec.poststop += "ifconfig ${external_interface} deletem ${host_epair}"; + exec.poststop += "ifconfig ${host_epair} destroy"; EOF else ## Generate bridged VNET config without static MAC address cat <<-EOF vnet; - vnet.interface = epair${uniq_epair_bridge}b; - exec.prestart += "ifconfig epair${uniq_epair_bridge} create"; - exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}a description \"vnet host interface for Bastille jail ${jail_name}\""; - exec.poststop += "ifconfig ${external_interface} deletem epair${uniq_epair_bridge}a"; - exec.poststop += "ifconfig epair${uniq_epair_bridge}a destroy"; + vnet.interface = ${jail_epair}; + exec.prestart += "ifconfig epair${_num} create"; + exec.prestart += "ifconfig ${external_interface} addm epair${_num}a"; + exec.prestart += "ifconfig epair${_num}a up name ${host_epair}"; + exec.prestart += "ifconfig epair${_num}b up name ${jail_epair}"; + exec.prestart += "ifconfig ${host_epair} description \"vnet host interface for Bastille jail ${jail_name}\""; + exec.poststop += "ifconfig ${external_interface} deletem ${host_epair}"; + exec.poststop += "ifconfig ${host_epair} destroy"; EOF fi else @@ -319,4 +363,4 @@ checkyesno() { return 1 ;; esac -} +} \ No newline at end of file From 589f19032ae246c941c60a0452498746c7d571df Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 18 Jan 2025 16:32:40 -0700 Subject: [PATCH 092/141] common: Allow name=if for bridge --- usr/local/share/bastille/common.sh | 240 +++++++++++++++++++---------- 1 file changed, 159 insertions(+), 81 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 654ff026..1f4e2fa0 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -31,7 +31,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Source config file -. /usr/local/etc/bastille/bastille.conf +if [ -f /usr/local/etc/bastille/bastille.conf ]; then + . /usr/local/etc/bastille/bastille.conf +fi COLOR_RED= COLOR_GREEN= @@ -50,24 +52,30 @@ enable_color() { . /usr/local/share/bastille/colors.pre.sh } +enable_debug() { + # Enable debug mode. + warn "***DEBUG MODE***" + set -x +} + # If "NO_COLOR" environment variable is present, or we aren't speaking to a # tty, disable output colors. if [ -z "${NO_COLOR}" ] && [ -t 1 ]; then enable_color fi -# Error/Info functions -error_notify() { - echo -e "${COLOR_RED}$*${COLOR_RESET}" 1>&2 -} - +# Notify message on error, and continue to next jail error_continue() { error_notify "$@" - # Disabling this shellcheck as we only ever call it inside of a loop # shellcheck disable=SC2104 continue } +# Notify message on error, but do not exit +error_notify() { + echo -e "${COLOR_RED}$*${COLOR_RESET}" 1>&2 +} + # Notify message on error and exit error_exit() { error_notify "$@" @@ -84,7 +92,8 @@ warn() { check_target_exists() { local _TARGET="${1}" - if [ ! -d "${bastille_jailsdir}"/"${_TARGET}" ]; then + local _jaillist="$(bastille list jails)" + if ! echo "${_jaillist}" | grep -Eq "^${_TARGET}$"; then return 1 else return 0 @@ -93,7 +102,7 @@ check_target_exists() { check_target_is_running() { local _TARGET="${1}" - if [ ! "$(/usr/sbin/jls name | awk "/^${_TARGET}$/")" ]; then + if ! jls name | grep -Eq "^${_TARGET}$"; then return 1 else return 0 @@ -102,20 +111,124 @@ check_target_is_running() { check_target_is_stopped() { local _TARGET="${1}" - if [ "$(/usr/sbin/jls name | awk "/^${_TARGET}$/")" ]; then + if jls name | grep -Eq "^${_TARGET}$"; then return 1 else return 0 fi } +get_jail_name() { + local _JID="${1}" + local _jailname="$(jls -j ${_JID} name 2>/dev/null)" + if [ -z "${_jailname}" ]; then + return 1 + else + echo "${_jailname}" + fi +} + +jail_autocomplete() { + local _TARGET="${1}" + local _jaillist="$(bastille list jails)" + local _AUTOTARGET="$(echo "${_jaillist}" | grep -E "^${_TARGET}")" + if [ -n "${_AUTOTARGET}" ]; then + if [ "$(echo "${_AUTOTARGET}" | wc -l)" -eq 1 ]; then + echo "${_AUTOTARGET}" + else + error_continue "Multiple jails found for ${_TARGET}:\n${_AUTOTARGET}" + return 1 + fi + else + return 2 + fi +} + +set_target() { + local _TARGET=${1} + JAILS="" + TARGET="" + if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then + target_all_jails + else + for _jail in ${_TARGET}; do + if [ ! -d "${bastille_jailsdir}/${_TARGET}" ] && echo "${_jail}" | grep -Eq '^[0-9]+$'; then + if get_jail_name "${_jail}" > /dev/null; then + _jail="$(get_jail_name ${_jail})" + else + error_continue "Error: JID \"${_jail}\" not found. Is jail running?" + fi + elif ! check_target_exists "${_jail}"; then + if jail_autocomplete "${_jail}" > /dev/null; then + _jail="$(jail_autocomplete ${_jail})" + elif [ $? -eq 2 ]; then + error_continue "Jail not found \"${_jail}\"" + else + exit 1 + fi + fi + TARGET="${TARGET} ${_jail}" + JAILS="${JAILS} ${_jail}" + done + export TARGET + export JAILS + fi +} + +set_target_single() { + local _TARGET="${1}" + if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then + error_exit "[all|ALL] not supported with this command." + elif [ "$(echo ${_TARGET} | wc -w)" -gt 1 ]; then + error_exit "Error: Command only supports a single TARGET." + elif [ ! -d "${bastille_jailsdir}/${_TARGET}" ] && echo "${_TARGET}" | grep -Eq '^[0-9]+$'; then + if get_jail_name "${_TARGET}" > /dev/null; then + _TARGET="$(get_jail_name ${_TARGET})" + else + error_exit "Error: JID \"${_TARGET}\" not found. Is jail running?" + fi + elif ! check_target_exists "${_TARGET}"; then + if jail_autocomplete "${_TARGET}" > /dev/null; then + _TARGET="$(jail_autocomplete ${_TARGET})" + elif [ $? -eq 2 ]; then + error_exit "Jail not found \"${_TARGET}\"" + else + exit 1 + fi + fi + TARGET="${_TARGET}" + JAILS="${_TARGET}" + export TARGET + export JAILS +} + +target_all_jails() { + local _JAILS="$(bastille list jails)" + JAILS="" + for _jail in ${_JAILS}; do + if [ -d "${bastille_jailsdir}/${_jail}" ]; then + JAILS="${JAILS} ${_jail}" + fi + done + export JAILS +} + +update_fstab() { + local _oldname="${1}" + local _newname="${2}" + local _fstab="${bastille_jailsdir}/${_newname}/fstab" + if [ -f "${_fstab}" ]; then + sed -i '' "s|${bastille_jailsdir}/${_oldname}/root/|${bastille_jailsdir}/${_newname}/root/|" "${_fstab}" + else + error_notify "Error: Failed to update fstab: ${_newmane}" + fi +} + generate_static_mac() { local jail_name="${1}" local external_interface="${2}" local external_interface_mac="$(ifconfig ${external_interface} | grep ether | awk '{print $2}')" - # Use the FreeBSD vendor MAC prefix for jail MAC prefix "58:9c:fc" local macaddr_prefix="58:9c:fc" - # Hash interface+jailname for jail MAC suffix local macaddr_suffix="$(echo -n "${external_interface_mac}${jail_name}" | sed 's#:##g' | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" if [ -z "${macaddr_prefix}" ] || [ -z "${macaddr_suffix}" ]; then error_notify "Failed to generate MAC address." @@ -140,12 +253,26 @@ generate_vnet_jail_netblock() { if [ "${_epair_if_count}" -gt 0 ]; then for _num in $(seq 0 "${epair_num_range}"); do if ! grep -Eosq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then - local uniq_epair_bridge="${_num}" + if [ "$(echo -n "e${_num}a_${jail_name}" | awk '{print length}')" -lt 16 ]; then + local host_epair=e${_num}a_${jail_name} + local jail_epair=e${_num}b_${jail_name} + else + local host_epair=epair${_num}a + local jail_epair=epair${_num}b + fi break fi done else - local uniq_epair_bridge="0" + if [ "$(echo -n "e0a_${jail_name}" | awk '{print length}')" -lt 16 ]; then + local _num=0 + local host_epair=e${_num}a_${jail_name} + local jail_epair=e${_num}b_${jail_name} + else + local _num=0 + local host_epair=epair${_num}a + local jail_epair=epair${_num}b + fi fi else if [ "${_bastille_if_count}" -gt 0 ]; then @@ -166,25 +293,29 @@ generate_vnet_jail_netblock() { generate_static_mac "${jail_name}" "${external_interface}" cat <<-EOF vnet; - vnet.interface = epair${uniq_epair_bridge}b; - exec.prestart += "ifconfig epair${uniq_epair_bridge} create"; - exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}a ether ${macaddr}a"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}b ether ${macaddr}b"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}a description \"vnet host interface for Bastille jail ${jail_name}\""; - exec.poststop += "ifconfig ${external_interface} deletem epair${uniq_epair_bridge}a"; - exec.poststop += "ifconfig epair${uniq_epair_bridge}a destroy"; + vnet.interface = ${jail_epair}; + exec.prestart += "ifconfig epair${_num} create"; + exec.prestart += "ifconfig ${external_interface} addm epair${_num}a"; + exec.prestart += "ifconfig epair${_num}a up name ${host_epair}"; + exec.prestart += "ifconfig epair${_num}b up name ${jail_epair}"; + exec.prestart += "ifconfig ${host_epair} ether ${macaddr}a"; + exec.prestart += "ifconfig ${jail_epair} ether ${macaddr}b"; + exec.prestart += "ifconfig ${host_epair} description \"vnet host interface for Bastille jail ${jail_name}\""; + exec.poststop += "ifconfig ${external_interface} deletem ${host_epair}"; + exec.poststop += "ifconfig ${host_epair} destroy"; EOF else ## Generate bridged VNET config without static MAC address cat <<-EOF vnet; - vnet.interface = epair${uniq_epair_bridge}b; - exec.prestart += "ifconfig epair${uniq_epair_bridge} create"; - exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a"; - exec.prestart += "ifconfig epair${uniq_epair_bridge}a description \"vnet host interface for Bastille jail ${jail_name}\""; - exec.poststop += "ifconfig ${external_interface} deletem epair${uniq_epair_bridge}a"; - exec.poststop += "ifconfig epair${uniq_epair_bridge}a destroy"; + vnet.interface = ${jail_epair}; + exec.prestart += "ifconfig epair${_num} create"; + exec.prestart += "ifconfig ${external_interface} addm epair${_num}a"; + exec.prestart += "ifconfig epair${_num}a up name ${host_epair}"; + exec.prestart += "ifconfig epair${_num}b up name ${jail_epair}"; + exec.prestart += "ifconfig ${host_epair} description \"vnet host interface for Bastille jail ${jail_name}\""; + exec.poststop += "ifconfig ${external_interface} deletem ${host_epair}"; + exec.poststop += "ifconfig ${host_epair} destroy"; EOF fi else @@ -213,58 +344,6 @@ EOF fi } -set_target() { - local _TARGET="${1}" - if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then - target_all_jails - else - check_target_exists "${_TARGET}" || error_exit "Jail not found \"${_TARGET}\"" - JAILS="${_TARGET}" - TARGET="${_TARGET}" - export JAILS - export TARGET - fi -} - -set_target_single() { - local _TARGET="${1}" - if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then - error_exit "[all|ALL] not supported with this command." - elif [ "$(echo ${_TARGET} | wc -w)" -gt 1 ]; then - error_exit "Error: Command only supports a single TARGET." - elif echo "${_TARGET}" | grep -Eq '^[0-9]+$'; then - if get_jail_name "${_TARGET}" > /dev/null; then - _TARGET="$(get_jail_name ${_TARGET})" - else - error_exit "Error: JID \"${_TARGET}\" not found. Is jail running?" - fi - elif - ! check_target_exists "${_TARGET}"; then - if jail_autocomplete "${_TARGET}" > /dev/null; then - _TARGET="$(jail_autocomplete ${_TARGET})" - elif [ $? -eq 2 ]; then - error_exit "Jail not found \"${_TARGET}\"" - else - exit 1 - fi - fi - TARGET="${_TARGET}" - JAILS="${_TARGET}" - export TARGET - export JAILS -} - -target_all_jails() { - local _JAILS="$(bastille list jails)" - JAILS="" - for _jail in ${_JAILS}; do - if [ -d "${bastille_jailsdir}/${_jail}" ]; then - JAILS="${JAILS} ${_jail}" - fi - done - export JAILS -} - checkyesno() { ## copied from /etc/rc.subr -- cedwards (20231125) ## issue #368 (lowercase values should be parsed) @@ -285,4 +364,3 @@ checkyesno() { ;; esac } - From 04f86c3f5badfb89b3b688726348871ed2827743 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 18 Jan 2025 16:38:29 -0700 Subject: [PATCH 093/141] clone: Allow name=if clone --- usr/local/share/bastille/clone.sh | 236 +++++++++++++++++++++--------- 1 file changed, 167 insertions(+), 69 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index 428bf9c8..290db01b 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -34,24 +34,78 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille clone TARGET NEW_NAME IPADDRESS" + error_notify "Usage: bastille clone [option(s)] TARGET NEW_NAME IP_ADDRESS" + cat << EOF + Options: + + -a | --auto Auto mode. Start/stop jail(s) if required. Cannot be used with [-l|--live]. + -l | --live Clone a running jail. ZFS only. Jail must be running. Cannot be used with [-f|--force]. + -x | --debug Enable debug mode. + +EOF + exit 1 } -# Handle special-case commands first -case "$1" in -help|-h|--help) - usage - ;; -esac +# Handle options. +AUTO=0 +LIVE=0 +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -a|--auto) + AUTO=1 + shift + ;; + -l|--live) + if ! checkyesno bastille_zfs_enable; then + error_exit "[-l|--live] can only be used with ZFS." + else + LIVE=1 + shift + fi + ;; + -x|--debug) + enable_debug + shift + ;; + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + a) AUTO=1 ;; + l) LIVE=1 ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" + esac + done + shift + ;; + *) + break + ;; + esac +done -if [ $# -ne 2 ]; then +if [ "${AUTO}" -eq 1 ] && [ "${LIVE}" -eq 1 ]; then + error_exit "[-a|--auto] cannot be used with [-l|--live]" +fi + +if [ $# -ne 3 ]; then usage fi -bastille_root_check +TARGET="${1}" +NEWNAME="${2}" +IP="${3}" -NEWNAME="${1}" -IP="${2}" +bastille_root_check +set_target_single "${TARGET}" + +## don't allow for dots(.) in container names +if echo "${NEWNAME}" | grep -q "[.]"; then + error_exit "Container names may not contain a dot(.)!" +fi validate_ip() { IPX_ADDR="ip4.addr" @@ -89,24 +143,43 @@ update_jailconf() { JAIL_CONFIG="${bastille_jailsdir}/${NEWNAME}/jail.conf" if [ -f "${JAIL_CONFIG}" ]; then if ! grep -qw "path = ${bastille_jailsdir}/${NEWNAME}/root;" "${JAIL_CONFIG}"; then - sed -i '' "s|host.hostname = ${TARGET};|host.hostname = ${NEWNAME};|" "${JAIL_CONFIG}" + sed -i '' "s|host.hostname = ${TARGET};|host.hostname = ${NEWNAME};|" "${JAIL_CONFIG}" sed -i '' "s|exec.consolelog = .*;|exec.consolelog = ${bastille_logsdir}/${NEWNAME}_console.log;|" "${JAIL_CONFIG}" sed -i '' "s|path = .*;|path = ${bastille_jailsdir}/${NEWNAME}/root;|" "${JAIL_CONFIG}" sed -i '' "s|mount.fstab = .*;|mount.fstab = ${bastille_jailsdir}/${NEWNAME}/fstab;|" "${JAIL_CONFIG}" sed -i '' "s|${TARGET} {|${NEWNAME} {|" "${JAIL_CONFIG}" - sed -i '' "s|${IPX_ADDR} = .*;|${IPX_ADDR} = ${IP};|" "${JAIL_CONFIG}" fi fi if grep -qw "vnet;" "${JAIL_CONFIG}"; then update_jailconf_vnet + else + _ip4="$(bastille config ${TARGET} get ip4.addr | sed 's/,/ /g')" + _ip6="$(bastille config ${TARGET} get ip6.addr | sed 's/,/ /g')" + # IP4 + if [ "${_ip4}" != "not set" ]; then + for _ip in ${_ip4}; do + _ip="$(echo ${_ip} | awk -F"|" '{print $2}')" + sed -i '' "/${IPX_ADDR} = .*/ s/${_ip}/${IP}/" "${JAIL_CONFIG}" + sed -i '' "/${IPX_ADDR} += .*/ s/${_ip}/127.0.0.1/" "${JAIL_CONFIG}" + done + fi + # IP6 + if [ "${_ip6}" != "not set" ]; then + for _ip in ${_ip6}; do + _ip="$(echo ${_ip} | awk -F"|" '{print $2}')" + sed -i '' "/${IPX_ADDR} = .*/ s/${_ip}/${IP}/" "${JAIL_CONFIG}" + sed -i '' "/${IPX_ADDR} += .*/ s/${_ip}/127.0.0.1/" "${JAIL_CONFIG}" + done + fi fi } update_jailconf_vnet() { - bastille_jail_rc_conf="${bastille_jailsdir}/${NEWNAME}/root/etc/rc.conf" + local _jail_conf="${bastille_jailsdir}/${NEWNAME}/jail.conf" + local _rc_conf="${bastille_jailsdir}/${NEWNAME}/root/etc/rc.conf" # Determine number of interfaces and define a uniq_epair - local _if_list="$(grep -Eo 'epair[0-9]+|bastille[0-9]+' ${JAIL_CONFIG} | sort -u)" + local _if_list="$(grep -Eo 'epair[0-9]+|bastille[0-9]+' ${_jail_conf} | sort -u)" for _if in ${_if_list}; do local _epair_if_count="$(grep -Eo 'epair[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" local _bastille_if_count="$(grep -Eo 'bastille[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" @@ -116,30 +189,53 @@ update_jailconf_vnet() { # Update bridged VNET config for _num in $(seq 0 "${epair_num_range}"); do if ! grep -oq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then - # Update jail.conf epair name - local uniq_epair_bridge="${_num}" - local _if_epaira="${_if}a" - local _if_epairb="${_if}b" - local _if_vnet="$(grep ${_if_epairb} "${bastille_jail_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" - sed -i '' "s|${_if}|epair${uniq_epair_bridge}|g" "${JAIL_CONFIG}" - # If jail had a static MAC, generate one for clone - if grep ether ${JAIL_CONFIG} | grep -qoc epair${uniq_epair_bridge}; then - local external_interface="$(grep "epair${uniq_epair_bridge}" ${JAIL_CONFIG} | grep -o '[^ ]* addm' | awk '{print $1}')" - generate_static_mac "${NEWNAME}" "${external_interface}" - sed -i '' "s|epair${uniq_epair_bridge}a ether.*:.*:.*:.*:.*:.*a\";|epair${uniq_epair_bridge}a ether ${macaddr}a\";|" "${JAIL_CONFIG}" - sed -i '' "s|epair${uniq_epair_bridge}b ether.*:.*:.*:.*:.*:.*b\";|epair${uniq_epair_bridge}b ether ${macaddr}b\";|" "${JAIL_CONFIG}" + # Generate new epair name + if [ "$(echo -n "e${_num}a_${NEWNAME}" | awk '{print length}')" -lt 16 ]; then + local _new_host_epair="e${_num}a_${NEWNAME}" + local _new_jail_epair="e${_num}b_${NEWNAME}" + else + local _new_host_epair="epair${_num}a" + local _new_jail_epair="epair${_num}b" fi - sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${JAIL_CONFIG}" + # Get epair name from TARGET + if grep -Eoq "e[0-9]+a_${TARGET}" "${_jail_conf}"; then + _target_host_epair="$(grep -Eo -m 1 "e[0-9]+a_${TARGET}" "${_jail_conf}")" + _target_jail_epair="$(grep -Eo -m 1 "e[0-9]+b_${TARGET}" "${_jail_conf}")" + else + _target_host_epair="${_if}a" + _target_jail_epair="${_if}b" + fi + # Replace epair name in jail.conf + sed -i '' "s|${_if}|epair${_num}|g" "${_jail_conf}" + # Replace host epair name in jail.conf + sed -i '' "s|up name ${_target_host_epair}|up name ${_new_host_epair}|g" "${_jail_conf}" + sed -i '' "s|${_target_host_epair} ether|${_new_host_epair} ether|g" "${_jail_conf}" + sed -i '' "s|deletem ${_target_host_epair}|deletem ${_new_host_epair}|g" "${_jail_conf}" + sed -i '' "s|${_target_host_epair} destroy|${_new_host_epair} destroy|g" "${_jail_conf}" + sed -i '' "s|${_target_host_epair} description|${_new_host_epair} description|g" "${_jail_conf}" + # Replace jail epair name in jail.conf + sed -i '' "s|= ${_target_jail_epair};|= ${_new_jail_epair};|g" "${_jail_conf}" + sed -i '' "s|up name ${_target_jail_epair}|up name ${_new_jail_epair}|g" "${_jail_conf}" + sed -i '' "s|${_target_jail_epair} ether|${_new_jail_epair} ether|g" "${_jail_conf}" + # If jail had a static MAC, generate one for clone + if grep -q ether ${_jail_conf}; then + local external_interface="$(grep "${_new_host_epair}" ${_jail_conf} | grep -o '[^ ]* addm' | awk '{print $1}')" + generate_static_mac "${NEWNAME}" "${external_interface}" + sed -i '' "s|${_new_host_epair} ether.*:.*:.*:.*:.*:.*a\";|${_new_host_epair} ether ${macaddr}a\";|" "${_jail_conf}" + sed -i '' "s|${_new_jail_epair} ether.*:.*:.*:.*:.*:.*b\";|${_new_jail_epair} ether ${macaddr}b\";|" "${_jail_conf}" + fi + sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${_jail_conf}" # Update /etc/rc.conf - sed -i '' "s|${_if_epairb}_name|epair${uniq_epair_bridge}b_name|" "${bastille_jail_rc_conf}" - if grep "vnet0" "${bastille_jail_rc_conf}" | grep -q "epair${uniq_epair_bridge}b_name"; then + local _jail_vnet="$(grep ${_target_jail_epair} "${_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" + sed -i '' "s|${_target_jail_epair}_name|${_new_jail_epair}_name|" "${_rc_conf}" + if grep "vnet0" "${_rc_conf}" | grep -q "${_new_jail_epair}_name"; then if [ "${IP}" = "0.0.0.0" ]; then - sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="SYNCDHCP" + sysrc -f "${_rc_conf}" ifconfig_vnet0="SYNCDHCP" else - sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="inet ${IP}" + sysrc -f "${_rc_conf}" ifconfig_vnet0="inet ${IP}" fi else - sysrc -f "${bastille_jail_rc_conf}" ifconfig_${_if_vnet}="SYNCDHCP" + sysrc -f "${_rc_conf}" ifconfig_${_jail_vnet}="SYNCDHCP" fi break fi @@ -150,26 +246,26 @@ update_jailconf_vnet() { if ! grep -oq "bastille${_num}" ${bastille_jailsdir}/*/jail.conf; then # Update jail.conf epair name local uniq_epair="bastille${_num}" - local _if_vnet="$(grep ${_if} "${bastille_jail_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" - sed -i '' "s|${_if}|${uniq_epair}|g" "${JAIL_CONFIG}" + local _if_vnet="$(grep ${_if} "${_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" + sed -i '' "s|${_if}|${uniq_epair}|g" "${_jail_conf}" # If jail had a static MAC, generate one for clone - if grep ether ${JAIL_CONFIG} | grep -qoc ${uniq_epair}; then - local external_interface="$(grep ${uniq_epair} ${JAIL_CONFIG} | grep -o 'addm.*' | awk '{print $3}' | sed 's/["|;]//g')" + if grep ether ${_jail_conf} | grep -qoc ${uniq_epair}; then + local external_interface="$(grep ${uniq_epair} ${_jail_conf} | grep -o 'addm.*' | awk '{print $3}' | sed 's/["|;]//g')" generate_static_mac "${NEWNAME}" "${external_interface}" - sed -i '' "s|${uniq_epair} ether.*:.*:.*:.*:.*:.*a\";|${uniq_epair} ether ${macaddr}a\";|" "${JAIL_CONFIG}" - sed -i '' "s|${uniq_epair} ether.*:.*:.*:.*:.*:.*b\";|${uniq_epair} ether ${macaddr}b\";|" "${JAIL_CONFIG}" + sed -i '' "s|${uniq_epair} ether.*:.*:.*:.*:.*:.*a\";|${uniq_epair} ether ${macaddr}a\";|" "${_jail_conf}" + sed -i '' "s|${uniq_epair} ether.*:.*:.*:.*:.*:.*b\";|${uniq_epair} ether ${macaddr}b\";|" "${_jail_conf}" fi - sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${JAIL_CONFIG}" + sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${_jail_conf}" # Update /etc/rc.conf - sed -i '' "s|ifconfig_e0b_${_if}_name|ifconfig_e0b_${uniq_epair}_name|" "${bastille_jail_rc_conf}" - if grep "vnet0" "${bastille_jail_rc_conf}" | grep -q ${uniq_epair}; then + sed -i '' "s|ifconfig_e0b_${_if}_name|ifconfig_e0b_${uniq_epair}_name|" "${_rc_conf}" + if grep "vnet0" "${_rc_conf}" | grep -q ${uniq_epair}; then if [ "${IP}" = "0.0.0.0" ]; then - sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="SYNCDHCP" + sysrc -f "${_rc_conf}" ifconfig_vnet0="SYNCDHCP" else - sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0=" inet ${IP} " + sysrc -f "${_rc_conf}" ifconfig_vnet0=" inet ${IP} " fi else - sysrc -f "${bastille_jail_rc_conf}" ifconfig_${_if_vnet}="SYNCDHCP" + sysrc -f "${_rc_conf}" ifconfig_${_if_vnet}="SYNCDHCP" fi break fi @@ -178,20 +274,21 @@ update_jailconf_vnet() { done } -update_fstab() { - # Update fstab to use the new name - FSTAB_CONFIG="${bastille_jailsdir}/${NEWNAME}/fstab" - if [ -f "${FSTAB_CONFIG}" ]; then - # Update additional fstab paths with new jail path - sed -i '' "s|${bastille_jailsdir}/${TARGET}/root/|${bastille_jailsdir}/${NEWNAME}/root/|" "${FSTAB_CONFIG}" - fi -} - clone_jail() { - # Attempt container clone - info "Attempting to clone '${TARGET}' to ${NEWNAME}..." + + info "Attempting to clone ${TARGET} to ${NEWNAME}..." + if ! [ -d "${bastille_jailsdir}/${NEWNAME}" ]; then if checkyesno bastille_zfs_enable; then + if [ "${LIVE}" -eq 1 ]; then + check_target_is_running "${TARGET}" || error_exit "[-l|--live] can only be used with a running jail." + else check_target_is_stopped "${TARGET}" || if [ "${FORCE}" -eq 1 ]; then + bastille stop "${TARGET}" + else + error_notify "Jail is running." + error_exit "Use [-f|--force] to force stop the jail, or [-l|--live] (ZFS only) to clone a running jail." + fi + fi if [ -n "${bastille_zfs_zpool}" ]; then # Replicate the existing container DATE=$(date +%F-%H%M%S) @@ -207,13 +304,13 @@ clone_jail() { zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NEWNAME}@bastille_clone_${DATE}" fi else - # Just clone the jail directory - # Check if container is running - if [ -n "$(/usr/sbin/jls name | awk "/^${TARGET}$/")" ]; then - error_exit "${TARGET} is running. See 'bastille stop ${TARGET}'." + # Perform container file copy (archive mode) + check_target_is_stopped "${TARGET}" || if [ "${FORCE}" -eq 1 ]; then + bastille stop "${TARGET}" + else + error_notify "Jail is running." + error_exit "Use [-f|--force] to force stop the jail." fi - - # Perform container file copy(archive mode) cp -a "${bastille_jailsdir}/${TARGET}" "${bastille_jailsdir}/${NEWNAME}" fi else @@ -222,7 +319,7 @@ clone_jail() { # Generate jail configuration files update_jailconf - update_fstab + update_fstab "${TARGET}" "${NEWNAME}" # Display the exist status if [ "$?" -ne 0 ]; then @@ -230,14 +327,15 @@ clone_jail() { else info "Cloned '${TARGET}' to '${NEWNAME}' successfully." fi + if [ "${AUTO}" -eq 1 ]; then + if [ "${LIVE}" -eq 0 ]; then + bastille start "${TARGET}" + fi + bastille start "${NEWNAME}" + fi } -## don't allow for dots(.) in container names -if echo "${NEWNAME}" | grep -q "[.]"; then - error_exit "Container names may not contain a dot(.)!" -fi - -## check if ip address is valid +# Check if IP address is valid. if [ -n "${IP}" ]; then validate_ip else From c26d470a7d681b8fe3074868949133547db88dce Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 18 Jan 2025 17:02:19 -0700 Subject: [PATCH 094/141] rename: Allow if=name --- usr/local/share/bastille/rename.sh | 154 +++++++++++++++++++++-------- 1 file changed, 113 insertions(+), 41 deletions(-) diff --git a/usr/local/share/bastille/rename.sh b/usr/local/share/bastille/rename.sh index 20fb8021..52e206f7 100644 --- a/usr/local/share/bastille/rename.sh +++ b/usr/local/share/bastille/rename.sh @@ -1,8 +1,6 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-3-Clause -# -# Copyright (c) 2018-2025, Christer Edwards +# Copyright (c) 2018-2024, Christer Edwards # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -34,11 +32,62 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille rename TARGET NEW_NAME" + error_notify "Usage: bastille rename [option(s)] TARGET NEW_NAME" + cat << EOF + Options: + + -a | --auto Auto mode. Start/stop jail(s) if required. + -x | --debug Enable debug mode. + +EOF + exit 1 } +# Handle options. +AUTO=0 +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -a|--auto) + AUTO=1 + shift + ;; + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + a) AUTO=1 ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" + esac + done + shift + ;; + *) + break + ;; + esac +done + +if [ "$#" -ne 2 ]; then + usage +fi + +TARGET="${1}" +NEWNAME="${2}" + +bastille_root_check +set_target_single "${TARGET}" +check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then + bastille stop "${TARGET}" +else + error_notify "Jail is running." + error_exit "Use [-a|--auto] to auto-stop the jail." +fi + validate_name() { - local NAME_VERIFY=${NEWNAME} + local NAME_VERIFY="${NEWNAME}" local NAME_SANITY="$(echo "${NAME_VERIFY}" | tr -c -d 'a-zA-Z0-9-_')" if [ -n "$(echo "${NAME_SANITY}" | awk "/^[-_].*$/" )" ]; then error_exit "Container names may not begin with (-|_) characters!" @@ -47,44 +96,64 @@ validate_name() { fi } -# Handle special-case commands first -case "$1" in -help|-h|--help) - usage - ;; -esac - -if [ $# -ne 1 ]; then - usage -fi - -bastille_root_check - -NEWNAME="${1}" - update_jailconf() { # Update jail.conf - JAIL_CONFIG="${bastille_jailsdir}/${NEWNAME}/jail.conf" - if [ -f "${JAIL_CONFIG}" ]; then - if ! grep -qw "path = ${bastille_jailsdir}/${NEWNAME}/root;" "${JAIL_CONFIG}"; then - sed -i '' "s|host.hostname.*=.*${TARGET};|host.hostname = ${NEWNAME};|" "${JAIL_CONFIG}" - sed -i '' "s|exec.consolelog.*=.*;|exec.consolelog = ${bastille_logsdir}/${NEWNAME}_console.log;|" "${JAIL_CONFIG}" - sed -i '' "s|path.*=.*;|path = ${bastille_jailsdir}/${NEWNAME}/root;|" "${JAIL_CONFIG}" - sed -i '' "s|mount.fstab.*=.*;|mount.fstab = ${bastille_jailsdir}/${NEWNAME}/fstab;|" "${JAIL_CONFIG}" - sed -i '' "s|${TARGET}.*{|${NEWNAME} {|" "${JAIL_CONFIG}" - # Rename vnet interface - sed -i '' "/vnet.interface/s|_${TARGET}\";|_${NEWNAME}\";|" "${JAIL_CONFIG}" - sed -i '' "/ifconfig/s|_${TARGET}|_${NEWNAME}|" "${JAIL_CONFIG}" + local _jail_conf="${bastille_jailsdir}/${NEWNAME}/jail.conf" + local _rc_conf="${bastille_jailsdir}/${NEWNAME}/root/etc/rc.conf" + if [ -f "${_jail_conf}" ]; then + if ! grep -qw "path = ${bastille_jailsdir}/${NEWNAME}/root;" "${_jail_conf}"; then + sed -i '' "s|host.hostname.*=.*${TARGET};|host.hostname = ${NEWNAME};|" "${_jail_conf}" + sed -i '' "s|exec.consolelog.*=.*;|exec.consolelog = ${bastille_logsdir}/${NEWNAME}_console.log;|" "${_jail_conf}" + sed -i '' "s|path.*=.*;|path = ${bastille_jailsdir}/${NEWNAME}/root;|" "${_jail_conf}" + sed -i '' "s|mount.fstab.*=.*;|mount.fstab = ${bastille_jailsdir}/${NEWNAME}/fstab;|" "${_jail_conf}" + sed -i '' "s|${TARGET}.*{|${NEWNAME} {|" "${_jail_conf}" + fi + if grep -qo "vnet;" "${_jail_conf}"; then + update_jailconf_vnet fi fi } -update_fstab() { - # Update fstab to use the new name - FSTAB_CONFIG="${bastille_jailsdir}/${NEWNAME}/fstab" - if [ -f "${FSTAB_CONFIG}" ]; then - sed -i '' "s|${bastille_jailsdir}/${TARGET}|${bastille_jailsdir}/${NEWNAME}|g" "${FSTAB_CONFIG}" - fi +update_jailconf_vnet() { + local _jail_conf="${bastille_jailsdir}/${NEWNAME}/jail.conf" + local _rc_conf="${bastille_jailsdir}/${NEWNAME}/root/etc/rc.conf" + # Change epair name (if needed) + local _if_list="$(grep -Eo 'epair[0-9]+|bastille[0-9]+' ${_jail_conf} | sort -u)" + for _if in ${_if_list}; do + if echo ${_if} | grep -Eoq 'epair[0-9]+'; then + # Check if epair name = jail name + local _epair_num="$(grep -Eo -m 1 "epair[0-9]+" "${_jail_conf}" | grep -Eo "[0-9]+")" + if grep -E "epair[0-9]+a" "${_jail_conf}" | grep -Eo "e[0-9]+a_${TARGET}"; then + local _target_host_epair="$(grep -Eo -m 1 "e[0-9]+a_${TARGET}" "${_jail_conf}")" + local _target_jail_epair="$(grep -Eo -m 1 "e[0-9]+b_${TARGET}" "${_jail_conf}")" + else + local _target_host_epair="$(grep -Eo -m 1 "epair[0-9]+a" "${_jail_conf}")" + local _target_jail_epair="$(grep -Eo -m 1 "epair[0-9]+b" "${_jail_conf}")" + fi + if [ "$(echo -n "e${_epair_num}a_${NEWNAME}" | awk '{print length}')" -lt 16 ]; then + # Generate new epair name + local _new_host_epair="e${_epair_num}a_${NEWNAME}" + local _new_jail_epair="e${_epair_num}b_${NEWNAME}" + else + local _new_host_epair="epair${_epair_num}a" + local _new_jail_epair="epair${_epair_num}b" + fi + # Replace host epair name in jail.conf + sed -i '' "s|up name ${_target_host_epair}|up name ${_new_host_epair}|g" "${_jail_conf}" + sed -i '' "s|${_target_host_epair} ether|${_new_host_epair} ether|g" "${_jail_conf}" + sed -i '' "s|deletem ${_target_host_epair}|deletem ${_new_host_epair}|g" "${_jail_conf}" + sed -i '' "s|${_target_host_epair} destroy|${_new_host_epair} destroy|g" "${_jail_conf}" + sed -i '' "s|${_target_host_epair} description|${_new_host_epair} description|g" "${_jail_conf}" + # Replace jail epair name in jail.conf + sed -i '' "s|= ${_target_jail_epair};|= ${_new_jail_epair};|g" "${_jail_conf}" + sed -i '' "s|up name ${_target_jail_epair}|up name ${_new_jail_epair}|g" "${_jail_conf}" + sed -i '' "s|${_target_jail_epair} ether|${_new_jail_epair} ether|g" "${_jail_conf}" + # Replace epair description + sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${_jail_conf}" + # Replace epair name in /etc/rc.conf + sed -i '' "/ifconfig/ s|${_target_jail_epair}|${_new_jail_epair}|g" "${_rc_conf}" + fi + done } change_name() { @@ -124,24 +193,27 @@ change_name() { fi fi - # Update jail configuration files accordingly + # Update jail conf files update_jailconf - update_fstab + update_fstab "${TARGET}" "${NEWNAME}" # Check exit status and notify if [ "$?" -ne 0 ]; then error_exit "An error has occurred while attempting to rename '${TARGET}'." else info "Renamed '${TARGET}' to '${NEWNAME}' successfully." + if [ "${AUTO}" -eq 1 ]; then + bastille start "${NEWNAME}" + fi fi } -## validate jail name +# Validate NEW_NAME if [ -n "${NEWNAME}" ]; then validate_name fi -## check if a jail already exists with the new name +# Check if a jail already exists with NEW_NAME if [ -d "${bastille_jailsdir}/${NEWNAME}" ]; then error_exit "Jail: ${NEWNAME} already exists." fi From 3f9d903f10656d2f8add96132a4026b7e67321f7 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 18 Jan 2025 17:44:38 -0700 Subject: [PATCH 095/141] bastille: rename+clone > no options command --- usr/local/bin/bastille | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index ba831d07..04f28e8c 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -164,10 +164,10 @@ version|-v|--version) help|-h|--help) usage ;; -bootstrap|create|destroy|etcupdate|export|htop|import|list|mount|rdr|restart|setup|start|top|umount|update|upgrade|verify) +bootstrap|clone|create|destroy|etcupdate|export|htop|import|list|mount|rdr|rename|restart|setup|start|top|umount|update|upgrade|verify) # Nothing "extra" to do for these commands. -- cwells ;; -clone|config|cmd|console|convert|cp|edit|limits|pkg|rcp|rename|service|stop|sysrc|tags|template|zfs) +config|cmd|console|convert|cp|edit|limits|pkg|rcp|service|stop|sysrc|tags|template|zfs) # Parse the target and ensure it exists. -- cwells if [ $# -eq 0 ]; then # No target was given, so show the command's help. -- cwells PARAMS='help' From abdf885c3a738c357772b416a51f146ea1cc631b Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 18 Jan 2025 17:47:13 -0700 Subject: [PATCH 096/141] common: Comment about MAC prefix --- usr/local/share/bastille/common.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 1f4e2fa0..8c7e57e9 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -228,6 +228,7 @@ generate_static_mac() { local jail_name="${1}" local external_interface="${2}" local external_interface_mac="$(ifconfig ${external_interface} | grep ether | awk '{print $2}')" + # Use FreeBSD vendor prefix for jail MAC prefix local macaddr_prefix="58:9c:fc" local macaddr_suffix="$(echo -n "${external_interface_mac}${jail_name}" | sed 's#:##g' | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" if [ -z "${macaddr_prefix}" ] || [ -z "${macaddr_suffix}" ]; then @@ -363,4 +364,4 @@ checkyesno() { return 1 ;; esac -} +} \ No newline at end of file From 73b9b149319d1614bee646377f1d6b79a5b4f5a7 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 18 Jan 2025 22:10:23 -0700 Subject: [PATCH 097/141] clone: typos --- usr/local/share/bastille/clone.sh | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index 290db01b..edb6c9f0 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -38,7 +38,7 @@ usage() { cat << EOF Options: - -a | --auto Auto mode. Start/stop jail(s) if required. Cannot be used with [-l|--live]. + -a | --auto Auto mode. Start/stop jail(s) if required. Cannot be used with [-l|--live]. -l | --live Clone a running jail. ZFS only. Jail must be running. Cannot be used with [-f|--force]. -x | --debug Enable debug mode. @@ -282,11 +282,11 @@ clone_jail() { if checkyesno bastille_zfs_enable; then if [ "${LIVE}" -eq 1 ]; then check_target_is_running "${TARGET}" || error_exit "[-l|--live] can only be used with a running jail." - else check_target_is_stopped "${TARGET}" || if [ "${FORCE}" -eq 1 ]; then + else check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then bastille stop "${TARGET}" else error_notify "Jail is running." - error_exit "Use [-f|--force] to force stop the jail, or [-l|--live] (ZFS only) to clone a running jail." + error_exit "Use [-a|--auto] to force stop the jail, or [-l|--live] (ZFS only) to clone a running jail." fi fi if [ -n "${bastille_zfs_zpool}" ]; then @@ -327,10 +327,7 @@ clone_jail() { else info "Cloned '${TARGET}' to '${NEWNAME}' successfully." fi - if [ "${AUTO}" -eq 1 ]; then - if [ "${LIVE}" -eq 0 ]; then - bastille start "${TARGET}" - fi + if [ "${AUTO}" -eq 1 ] || [ "${LIVE}" -eq 1 ]; then bastille start "${NEWNAME}" fi } From ef8a4e209fceb4d885ddd1d171427de8821a1d40 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 18 Jan 2025 22:14:13 -0700 Subject: [PATCH 098/141] clone: more typos --- usr/local/share/bastille/clone.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index edb6c9f0..6d2db6f8 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -305,11 +305,11 @@ clone_jail() { fi else # Perform container file copy (archive mode) - check_target_is_stopped "${TARGET}" || if [ "${FORCE}" -eq 1 ]; then + check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then bastille stop "${TARGET}" else error_notify "Jail is running." - error_exit "Use [-f|--force] to force stop the jail." + error_exit "Use [-a|--auto] to force stop the jail." fi cp -a "${bastille_jailsdir}/${TARGET}" "${bastille_jailsdir}/${NEWNAME}" fi From b2ba31984e4fbac05ea56f61c6b78c45090d5514 Mon Sep 17 00:00:00 2001 From: ejherlig Date: Sun, 19 Jan 2025 12:25:02 +0000 Subject: [PATCH 099/141] Create config.rst The "config" subcommand exists but is not documented. This file documents the subcommand with a few examples. --- docs/chapters/subcommands/config.rst | 32 ++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 docs/chapters/subcommands/config.rst diff --git a/docs/chapters/subcommands/config.rst b/docs/chapters/subcommands/config.rst new file mode 100644 index 00000000..aa583ca4 --- /dev/null +++ b/docs/chapters/subcommands/config.rst @@ -0,0 +1,32 @@ +======= +config +======= + +Gets or sets properties for a target container. + +.. code-block:: shell + + Usage: bastille config TARGET get|set propertyName [newValue] + +Getting a property that *is* defined in jail.conf: + +.. code-block:: shell + + ishmael ~ # bastille config azkaban get ip4.addr + 192.168.2.23 + +Getting a property that *is not* defined in jail.conf + +.. code-block:: shell + + ishmael ~ # bastille config azkaban get notaproperty + not set + +Setting a property: + +.. code-block:: shell + + ishmael ~ # bastille config azkaban set ip4.addr 192.168.2.24 + A restart is required for the changes to be applied. See 'bastille restart azkaban'. + +The restart message will appear every time a property is set. From 1fc84bc16876116aa08df5848fbd03e4c6d54837 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 19 Jan 2025 08:14:24 -0700 Subject: [PATCH 100/141] clone: Fix retrieving ext if MAC on bridge --- usr/local/share/bastille/clone.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index 6d2db6f8..c967cd85 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -205,8 +205,6 @@ update_jailconf_vnet() { _target_host_epair="${_if}a" _target_jail_epair="${_if}b" fi - # Replace epair name in jail.conf - sed -i '' "s|${_if}|epair${_num}|g" "${_jail_conf}" # Replace host epair name in jail.conf sed -i '' "s|up name ${_target_host_epair}|up name ${_new_host_epair}|g" "${_jail_conf}" sed -i '' "s|${_target_host_epair} ether|${_new_host_epair} ether|g" "${_jail_conf}" @@ -219,11 +217,14 @@ update_jailconf_vnet() { sed -i '' "s|${_target_jail_epair} ether|${_new_jail_epair} ether|g" "${_jail_conf}" # If jail had a static MAC, generate one for clone if grep -q ether ${_jail_conf}; then - local external_interface="$(grep "${_new_host_epair}" ${_jail_conf} | grep -o '[^ ]* addm' | awk '{print $1}')" + local external_interface="$(grep "epair${_num}a" ${_jail_conf} | grep -o '[^ ]* addm' | awk '{print $1}')" generate_static_mac "${NEWNAME}" "${external_interface}" sed -i '' "s|${_new_host_epair} ether.*:.*:.*:.*:.*:.*a\";|${_new_host_epair} ether ${macaddr}a\";|" "${_jail_conf}" sed -i '' "s|${_new_jail_epair} ether.*:.*:.*:.*:.*:.*b\";|${_new_jail_epair} ether ${macaddr}b\";|" "${_jail_conf}" fi + # Replace epair name in jail.conf + sed -i '' "s|${_if}|epair${_num}|g" "${_jail_conf}" + # Replace epair description sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${_jail_conf}" # Update /etc/rc.conf local _jail_vnet="$(grep ${_target_jail_epair} "${_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" From c1537e2a206cdf1c7afcaafe00c1a538a72a2242 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 19 Jan 2025 08:22:12 -0700 Subject: [PATCH 101/141] clone: Spacing -1 --- usr/local/share/bastille/clone.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index c967cd85..283def73 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -222,9 +222,9 @@ update_jailconf_vnet() { sed -i '' "s|${_new_host_epair} ether.*:.*:.*:.*:.*:.*a\";|${_new_host_epair} ether ${macaddr}a\";|" "${_jail_conf}" sed -i '' "s|${_new_jail_epair} ether.*:.*:.*:.*:.*:.*b\";|${_new_jail_epair} ether ${macaddr}b\";|" "${_jail_conf}" fi - # Replace epair name in jail.conf - sed -i '' "s|${_if}|epair${_num}|g" "${_jail_conf}" - # Replace epair description + # Replace epair name in jail.conf + sed -i '' "s|${_if}|epair${_num}|g" "${_jail_conf}" + # Replace epair description sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${_jail_conf}" # Update /etc/rc.conf local _jail_vnet="$(grep ${_target_jail_epair} "${_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" From 10c82964e3b75dc34a30f4aec9f9cbfc22678495 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 19 Jan 2025 08:27:41 -0700 Subject: [PATCH 102/141] clone: Change MAC after IF --- usr/local/share/bastille/clone.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index 283def73..9c945f94 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -215,6 +215,8 @@ update_jailconf_vnet() { sed -i '' "s|= ${_target_jail_epair};|= ${_new_jail_epair};|g" "${_jail_conf}" sed -i '' "s|up name ${_target_jail_epair}|up name ${_new_jail_epair}|g" "${_jail_conf}" sed -i '' "s|${_target_jail_epair} ether|${_new_jail_epair} ether|g" "${_jail_conf}" + # Replace epair name in jail.conf + sed -i '' "s|${_if}|epair${_num}|g" "${_jail_conf}" # If jail had a static MAC, generate one for clone if grep -q ether ${_jail_conf}; then local external_interface="$(grep "epair${_num}a" ${_jail_conf} | grep -o '[^ ]* addm' | awk '{print $1}')" @@ -222,8 +224,6 @@ update_jailconf_vnet() { sed -i '' "s|${_new_host_epair} ether.*:.*:.*:.*:.*:.*a\";|${_new_host_epair} ether ${macaddr}a\";|" "${_jail_conf}" sed -i '' "s|${_new_jail_epair} ether.*:.*:.*:.*:.*:.*b\";|${_new_jail_epair} ether ${macaddr}b\";|" "${_jail_conf}" fi - # Replace epair name in jail.conf - sed -i '' "s|${_if}|epair${_num}|g" "${_jail_conf}" # Replace epair description sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${_jail_conf}" # Update /etc/rc.conf From 4fc9426bc129ac069b89b0e59adc93fc787fd380 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 20 Jan 2025 12:36:27 -0700 Subject: [PATCH 103/141] upgrade: let users know to restart and run install command again --- usr/local/share/bastille/upgrade.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/upgrade.sh b/usr/local/share/bastille/upgrade.sh index 2be09435..7df54354 100644 --- a/usr/local/share/bastille/upgrade.sh +++ b/usr/local/share/bastille/upgrade.sh @@ -152,7 +152,7 @@ jail_upgrade() { # Update "osrelease" entry inside jail.conf sed -i '' "/osrelease/ s|${_oldrelease}|${_newrelease}|g" "${bastille_jailsdir}/${TARGET}/jail.conf" echo - echo -e "${COLOR_YELLOW}Please run 'bastille upgrade ${TARGET} install' to finish installing updates.${COLOR_RESET}" + echo -e "${COLOR_YELLOW}Please run 'bastille upgrade ${TARGET} install', restart the jail, then run 'bastille upgrade ${TARGET} install' again to finish installing updates.${COLOR_RESET}" fi } From 0bf87b1980b7e2626036543077748d9b06829533 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:28:33 -0700 Subject: [PATCH 104/141] mount: Add debug mode --- usr/local/share/bastille/mount.sh | 33 ++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index 5895823a..9c7a450e 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -34,15 +34,34 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille mount TARGET HOST_PATH JAIL_PATH [filesystem_type options dump pass_number]" + error_notify "Usage: bastille mount TARGET HOST_PATH JAIL_PATH [filesystem_type options dump pass_number]" + cat << EOF + Options: + + -x | --debug Enable debug mode. + +EOF + exit 1 } -# Handle special-case commands first. -case "${1}" in - help|-h|--help) - usage - ;; -esac +# Handle options. +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -x|--debug) + enable_debug + shift + ;; + -*) + error_exit "Unknown Option: \"${1}\"" + ;; + *) + break + ;; + esac +done if [ "$#" -lt 3 ] || [ "$#" -gt 7 ]; then usage From caee31a62118244776d4e20b89363ff4dd4db58e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:30:23 -0700 Subject: [PATCH 105/141] mount: Spacing --- usr/local/share/bastille/mount.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index 9c7a450e..5aa624f6 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -47,9 +47,9 @@ EOF # Handle options. while [ "$#" -gt 0 ]; do case "${1}" in - -h|--help|help) - usage - ;; + -h|--help|help) + usage + ;; -x|--debug) enable_debug shift From 391abe2335c35158d8f53eeff5df689e05383b31 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:32:35 -0700 Subject: [PATCH 106/141] mount: just change "must start with" to "must include" for documentation --- usr/local/share/bastille/mount.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index 5aa624f6..4ff5d88c 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -110,7 +110,7 @@ elif [ ! -e "${_hostpath}" ] || [ "${_type}" != "nullfs" ]; then usage fi -# Mount permissions,options must start with one of "ro, rw, rq, sw, xx" +# Mount permissions,options must include one of "ro, rw, rq, sw, xx" if ! echo "${_perms}" | grep -Eq '(ro|rw|rq|sw|xx)(,.*)?$'; then error_notify "Detected invalid mount permissions in FSTAB." warn "Format: /host/path /jail/path nullfs ro 0 0" From a49d58124d4da40a6e3cd48caddbdf65a2c6215a Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:33:20 -0700 Subject: [PATCH 107/141] docs: Mount fix --- docs/chapters/subcommands/mount.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/chapters/subcommands/mount.rst b/docs/chapters/subcommands/mount.rst index 172799ad..2f37f47b 100644 --- a/docs/chapters/subcommands/mount.rst +++ b/docs/chapters/subcommands/mount.rst @@ -10,7 +10,7 @@ Syntax follows standard `/etc/fstab` format: Usage: bastille mount TARGET HOST_PATH JAIL_PATH [filesystem_type options dump pass_number] -The 'options' string can include a comma-separated list of mount options, but must start with one of (rw,ro,rq,sw,xx) according to fstab documentation. +The 'options' string can include a comma-separated list of mount options, but must include one of (rw,ro,rq,sw,xx) according to fstab documentation. Example: Mount a tmpfs filesystem with options. .. code-block:: shell From c27f0a7408374f5c66fcf7a7e61ea2582819a515 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:36:54 -0700 Subject: [PATCH 108/141] mount: Add options block to notify message --- usr/local/share/bastille/mount.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index 4ff5d88c..db69638d 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -34,7 +34,7 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_notify "Usage: bastille mount TARGET HOST_PATH JAIL_PATH [filesystem_type options dump pass_number]" + error_notify "Usage: bastille mount [option(s)] TARGET HOST_PATH JAIL_PATH [filesystem_type options dump pass_number]" cat << EOF Options: From 90777ca37e52517c3dfa53a9935cbd2b111c0601 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:38:47 -0700 Subject: [PATCH 109/141] mount: Stay consistent with "Unknown Option." --- usr/local/share/bastille/mount.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index db69638d..d9281696 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -55,7 +55,7 @@ while [ "$#" -gt 0 ]; do shift ;; -*) - error_exit "Unknown Option: \"${1}\"" + error_exit "Unknown Option." ;; *) break From c790e65f13fb9c61fb95a993dce651a987f1a2c2 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:42:39 -0700 Subject: [PATCH 110/141] mount: Call usage on unknown option --- usr/local/share/bastille/mount.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index d9281696..7903eedb 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -54,8 +54,9 @@ while [ "$#" -gt 0 ]; do enable_debug shift ;; - -*) - error_exit "Unknown Option." + --*|-*) + error_notify "Unknown Option." + usage ;; *) break From 22831e4b8296a83b4f36a3756c1bda8e09f7d264 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:47:58 -0700 Subject: [PATCH 111/141] cp: Exit it -j and -r are both set --- usr/local/share/bastille/cp.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/cp.sh b/usr/local/share/bastille/cp.sh index b0141327..ac6d8c2d 100644 --- a/usr/local/share/bastille/cp.sh +++ b/usr/local/share/bastille/cp.sh @@ -39,7 +39,7 @@ usage() { Options: -j | --jail Jail mode. Copy files from jail to jail(s). - Syntax is [-j jail:srcpath jail:dstpath] + Syntax: [-j jail:srcpath jail:dstpath] -r | --reverse Reverse copy files from jail to host. -q | --quiet Suppress output. -x | --debug Enable debug mode. @@ -95,6 +95,10 @@ if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then usage fi +if [ "${JAIL_MODE}" -eq 1 ] && [ "${REVERSE_MODE}" -eq 1 ]; then + error_exit "[-j|--jail] cannot be used with [-r|reverse]" +fi + if [ "${JAIL_MODE}" -eq 1 ]; then SOURCE_TARGET="$(echo ${1} | awk -F":" '{print $1}')" SOURCE_PATH="$(echo ${1} | awk -F":" '{print $2}')" @@ -142,4 +146,4 @@ else error_continue "CP failed: ${host_path} -> ${jail_path}" fi done -fi \ No newline at end of file +fi From 5746af35816a0535ff7b822767db099df95bdab5 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:50:06 -0700 Subject: [PATCH 112/141] common: Add debug mode --- usr/local/share/bastille/common.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 654ff026..dd8be78c 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -61,6 +61,12 @@ error_notify() { echo -e "${COLOR_RED}$*${COLOR_RESET}" 1>&2 } +enable_debug() { + # Enable debug mode. + warn "***DEBUG MODE***" + set -x +} + error_continue() { error_notify "$@" # Disabling this shellcheck as we only ever call it inside of a loop From dee9ab08652a3af6ec3ab57bbe825a7f0bb58813 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:52:16 -0700 Subject: [PATCH 113/141] mount: Remove debug option for later addition --- usr/local/share/bastille/mount.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index 7903eedb..b9b2da2c 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -50,10 +50,6 @@ while [ "$#" -gt 0 ]; do -h|--help|help) usage ;; - -x|--debug) - enable_debug - shift - ;; --*|-*) error_notify "Unknown Option." usage From f0072cebbd1324dcee819931df85074bedba168c Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 20 Jan 2025 18:53:04 -0700 Subject: [PATCH 114/141] mount: Do not show debug as an option --- usr/local/share/bastille/mount.sh | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index b9b2da2c..e2c060e6 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -34,14 +34,7 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_notify "Usage: bastille mount [option(s)] TARGET HOST_PATH JAIL_PATH [filesystem_type options dump pass_number]" - cat << EOF - Options: - - -x | --debug Enable debug mode. - -EOF - exit 1 + error_exit "Usage: bastille mount [option(s)] TARGET HOST_PATH JAIL_PATH [filesystem_type options dump pass_number]" } # Handle options. From d4d747de051b7926a0b645650b16e363dda5aafd Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Mon, 20 Jan 2025 19:25:02 -0700 Subject: [PATCH 115/141] create: Do not allow only numbers in name --- usr/local/share/bastille/create.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index 0f47f17c..9160835f 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -68,6 +68,8 @@ validate_name() { error_exit "Container names may not begin with (-|_) characters!" elif [ "${NAME_VERIFY}" != "${NAME_SANITY}" ]; then error_exit "Container names may not contain special characters!" + elif echo "${NAME_VERIFY}" | grep -qE '^[0-9]+$'; then + error_exit "Container names may not contain only numbers." fi } From af78f2b74d1ff9696ff59c22dfb82b4372f6b633 Mon Sep 17 00:00:00 2001 From: JRGTH Date: Tue, 21 Jan 2025 05:55:37 -0400 Subject: [PATCH 116/141] Initial 'bastille setup' cmd rewrite/enhancements This PR will add the Initial 'bastille setup' command rewrite and enhancements, includes the ZFS activation helper, also further enhancements will be added accordingly. Further testing/bug reporting welcome. --- usr/local/share/bastille/setup.sh | 879 +++++++++++++++++++++++++++--- 1 file changed, 806 insertions(+), 73 deletions(-) diff --git a/usr/local/share/bastille/setup.sh b/usr/local/share/bastille/setup.sh index 020d2cf4..bd22d4fa 100644 --- a/usr/local/share/bastille/setup.sh +++ b/usr/local/share/bastille/setup.sh @@ -1,7 +1,5 @@ #!/bin/sh # -# SPDX-License-Identifier: BSD-3-Clause -# # Copyright (c) 2018-2025, Christer Edwards # All rights reserved. # @@ -30,41 +28,410 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -bastille_config="/usr/local/etc/bastille/bastille.conf" +# Let's set some predefined/fallback variables. +bastille_config_path="/usr/local/etc/bastille" +bastille_config="${bastille_config_path}/bastille.conf" +bastille_prefix_default="/usr/local/bastille" +bastille_zfsprefix_default="bastille" +bastille_ifbridge_name="bastille1" + . /usr/local/share/bastille/common.sh # shellcheck source=/usr/local/etc/bastille/bastille.conf . ${bastille_config} usage() { - error_exit "Usage: bastille setup [pf|network|zfs|vnet]" + # Build an independent usage for the `setup` command. + # No short options here for the special purpose --long-options, + # so we can reserve short options for future adds, also the user + # must genuinely agreed on configuration reset/restore so let them type for it. + error_notify "Usage: bastille setup [option]" + + cat << EOF + Options: + + -p | --firewall -- Attempt to configure bastille PF firewall. + -n | --network -- Attempt to configure network loopback interface. + -v | --vnet -- Attempt to configure VNET bridge interface [bastille1]. + -z | --zfs -- Activates ZFS storage features and benefits for bastille. + --conf-network-reset -- Restore bastille default Network options on the config file. + --conf-storage-reset -- Restore bastille default ZFS storage options on the config file. + --conf-restore-clean -- Restore bastille default config file from bastille.conf.sample file. + +EOF + exit 1 } -# Check for too many args +input_error() { + error_exit "Invalid user input, aborting!" +} + +config_runtime() { + # Run here variables considered to be required by bastille by default silently. + if ! sysrc -qn bastille_enable | grep -qi "yes"; then + sysrc bastille_enable="YES" >/dev/null 2>&1 + fi +} + +# Check for too many args. if [ $# -gt 1 ]; then usage fi -# Configure bastille loopback network interface -configure_network() { - info "Configuring ${bastille_network_loopback} loopback interface" - sysrc cloned_interfaces+=lo1 - sysrc ifconfig_lo1_name="${bastille_network_loopback}" +# Handle special-case commands first. +case "${1}" in + help|--help|-h) + usage + ;; +esac - info "Bringing up new interface: ${bastille_network_loopback}" +user_canceled() { + # Don't use 'error_exit' here as this only should inform the user, not panic them. + info "Cancelled by user, exiting!" + exit 1 +} + +config_backup() { + # Create bastille configuration backup with system time appended. + # This should be called each time `bastille setup` attempts to + # write to bastille configuration file. + BACKUP_DATE=$(date +%Y%m%d-%H%M%S) + cp "${bastille_config}" "${bastille_config}.${BACKUP_DATE}" + BACKUP_NAME="${bastille_config}.${BACKUP_DATE}" + info "Config backup created in: [${BACKUP_NAME}]" +} + +config_network_reset() { + # Restore bastille default network options. + warn "Performing Network configuration reset, requested by the user..." + read -p "$(warn "Do you really want to reset 'bastille' network configuration? [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + local VAR_ITEMS="bastille_network_loopback=bastille0 bastille_network_pf_ext_if=ext_if + bastille_network_pf_table=jails bastille_network_shared= bastille_network_gateway= bastille_network_gateway6=" + for _item in ${VAR_ITEMS}; do + sysrc -f "${bastille_config}" ${_item} + done + info "Network configuration has been reset successfully!" + exit 0 + ;; + [Nn]|[Nn][Oo]) + user_canceled + ;; + *) + input_error + ;; + esac +} + +config_storage_reset() { + # Restore bastille default ZFS storage options. + warn "Performing ZFS configuration reset, requested by the user..." + read -p "$(warn "Do you really want to reset 'bastille' ZFS configuration? [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + local VAR_ITEMS="bastille_zfs_enable= bastille_zfs_zpool= bastille_zfs_prefix=bastille" + for _item in ${VAR_ITEMS}; do + sysrc -f "${bastille_config}" ${_item} + done + + # Let's configure variables with complex values individually to keep it simple/readable for everyone. + sysrc -f "${bastille_config}" bastille_zfs_options="-o compress=lz4 -o atime=off" + sysrc -f "${bastille_config}" bastille_prefix="${bastille_prefix_default}" + info "ZFS configuration has been reset successfully!" + exit 0 + ;; + [Nn]|[Nn][Oo]) + user_canceled + ;; + *) + input_error + ;; + esac +} + +config_restore_global() { + local _response + # This will restore bastille default configuration file from the sample config file. + # Be aware that if the sample configuration file is missing, we can generate a new one, + # but that's highly unlikely to happen so will keep the code smaller here. + warn "Performing Bastille default configuration restore, requested by the user..." + read -p "$(warn "Do you really want to restore 'bastille' default configuration file and start over? [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + config_backup + if [ -f "${bastille_config}.sample" ]; then + mv "${bastille_config}" "${bastille_config}.${BACKUP_DATE}" + cp "${bastille_config}.sample" "${bastille_config}" + else + error_exit "Bastille sample configuration file is missing, exiting." + fi + info "Bastille configuration file restored successfully!" + exit 0 + ;; + [Nn]|[Nn][Oo]) + user_canceled + ;; + *) + input_error + ;; + esac +} + +get_zfs_params() { + info "Reading on-disk and bastille ZFS config parameters..." + # Always try to detect and recover on-disk ZFS bastille configuration first. + # Bastille ZFS prefix is always set to "bastille" in the config file by default, + # so will keep things simple here, or considered custom setup if this variable is changed. + BARTILLE_ROOTFS=$(mount | awk '/ \/ / {print $1}') + BASTILLE_UFSBOOT= + BASTILLE_ZFSPOOL= + BASTILLE_PREFIXDEF= + BASTILLE_ZFSENABLE= + BASTILLE_PREFIX_MATCH= + + # Check if the system boots from ZFS. + if echo "${BARTILLE_ROOTFS}" | grep -q -m 1 -E "^/dev/"; then + # Assume the host is running from UFS. + info "This system doesn't boot from ZFS, looking for alternate configuration." + BASTILLE_UFSBOOT="1" + fi + + BASTILLE_PREFIXCONF=$(sysrc -qn -f "${bastille_config}" bastille_prefix) + BASTILLE_PREFIXZFS=$(sysrc -qn -f "${bastille_config}" bastille_zfs_prefix) + + if [ -z "${BASTILLE_PREFIXZFS}" ]; then + BASTILLE_PREFIXZFS="${bastille_zfsprefix_default}" + fi + + if [ -z "${BASTILLE_UFSBOOT}" ]; then + if [ "${BASTILLE_PREFIXZFS}" != "${bastille_zfsprefix_default}" ]; then + BASTILLE_CUSTOM_CONFIG="1" + fi + fi + + # Try to determine "zroot" pool name as it may happens that the user + # customized the "zroot" pool name during the initial FreeBSD installation. + if [ -z "${BASTILLE_UFSBOOT}" ]; then + #BASTILLE_ZFSPOOL=$(df ${bastille_config_path} 2>/dev/null | sed 1d | awk -F '/' '{print $1}') + BASTILLE_ZFSPOOL=$(zfs list -H ${bastille_config_path} 2>/dev/null | awk -F '/' '{print $1}') + fi + + if [ -z "${BASTILLE_UFSBOOT}" ]; then + BASTILLE_PREFIXDEF=$(zfs list -H "${BASTILLE_ZFSPOOL}/${BASTILLE_PREFIXZFS}" 2>/dev/null | awk '{print $5}') + fi + + if [ -n "${BASTILLE_UFSBOOT}" ]; then + # Make sure bastille_prefix is listed by ZFS then try to get bastille_zfs_pool from it. + # Make some additional checks for non ZFS boot systems, also rely on some 'bastille.conf' ZFS parameters. + BASTILLE_PREFIXLOOK=$(zfs list -H "${BASTILLE_PREFIXCONF}" 2>/dev/null | awk '{print $1}') + BASTILLE_ZFSPOOL=$(zfs list -H "${BASTILLE_PREFIXLOOK}" 2>/dev/null | awk -F '/' '{print $1}') + BASTILLE_PREFIXDEF=$(zfs list -H "${BASTILLE_PREFIXCONF}" 2>/dev/null | awk '{print $5}') + + else + # Fallback to default config. + if [ -z "${BASTILLE_PREFIXDEF}" ]; then + BASTILLE_PREFIXDEF="${bastille_prefix_default}" + fi + fi + + if [ "${BASTILLE_PREFIXDEF}" = "${BASTILLE_PREFIXCONF}" ]; then + BASTILLE_PREFIX_MATCH="1" + fi + + # Update 'bastille_prefix' if a custom dataset is detected while reading on-disk configuration. + if [ ! -d "${bastille_prefix}" ] || [ -n "${ZFS_DATASET_DETECT}" ] || [ -n "${BASTILLE_PREFIXDEF}" ]; then + BASTILLE_ZFSENABLE="YES" + bastille_prefix="${BASTILLE_PREFIXDEF}" + else + BASTILLE_ZFSENABLE="NO" + if [ -z "${BASTILLE_UFSBOOT}" ]; then + BASTILLE_PREFIXZFS="" + fi + fi +} + +config_validation(){ + # Perform a basic bastille ZFS configuration check, + if [ -d "${bastille_prefix}" ] && [ -n "${BASTILLE_PREFIX_MATCH}" ] && echo "${bastille_zfs_enable}" | grep -qi "yes" \ + && zfs list "${bastille_zfs_zpool}/${bastille_zfs_prefix}" >/dev/null 2>&1; then + info "Looks like Bastille ZFS storage features has been activated successfully!." + exit 0 + else + if [ ! -d "${bastille_prefix}" ] && [ -z "${BASTILLE_ZFSPOOL}" ]; then + zfs_initial_activation + else + if ! echo "${bastille_zfs_enable}" | grep -qi "no"; then + + # Inform the user bastille ZFS configuration has been tampered and/or on-disk ZFS config has changed. + error_exit "Bastille ZFS misconfiguration detected, please refer to 'bastille.conf' or see 'bastille setup --config-reset'." + fi + fi + fi +} + +show_zfs_params() { + # Show a brief info of the detected and/or pending bastille ZFS configuration parameters. + # Don't need to show bastille zfs enable as this will be enabled by default. + info "*************************************" + info "Bastille Storage Prefix: [${BASTILLE_PREFIXDEF}]" + info "Bastille ZFS Pool: [${BASTILLE_ZFSPOOL}]" + info "Bastille ZFS Prefix: [${BASTILLE_PREFIXZFS}]" + info "*************************************" +} + +write_zfs_opts() { + # Write/update to bastille config file the required and/or misssing parameters. + if [ -z "${bastille_prefix}" ] || [ "${BASTILLE_PREFIXDEF}" != "${bastille_prefix_default}" ]; then + if [ -z "${BASTILLE_PREFIX_MATCH}" ]; then + sysrc -f "${bastille_config}" bastille_prefix="${BASTILLE_PREFIXDEF}" + fi + else + if [ -z "${BASTILLE_PREFIXCONF}" ] && [ -n "${BASTILLE_PREFIXDEF}" ]; then + sysrc -f "${bastille_config}" bastille_prefix="${BASTILLE_PREFIXDEF}" + fi + fi + + if [ -z "${bastille_zfs_enable}" ]; then + sysrc -f "${bastille_config}" bastille_zfs_enable="${BASTILLE_ZFSENABLE}" + fi + if [ -z "${bastille_zfs_zpool}" ]; then + sysrc -f "${bastille_config}" bastille_zfs_zpool="${BASTILLE_ZFSPOOL}" + fi + if [ -z "${bastille_zfs_prefix}" ] || [ "${BASTILLE_PREFIXDEF}" != "${bastille_zfs_prefix}" ]; then + sysrc -f "${bastille_config}" bastille_zfs_prefix="${BASTILLE_PREFIXZFS}" + fi + info "ZFS has been enabled in bastille configuration successfully!" +} + +create_zfs_dataset(){ + info "Creating ZFS dataset [${BASTILLE_ZFSPOOL}/${BASTILLE_PREFIXZFS}] for bastille..." + + if [ -n "${BASTILLE_CONFIG_USER}" ]; then + bastille_prefix="${BASTILLE_PREFIXDEF}" + fi + + # shellcheck disable=SC1073 + if zfs list "${BASTILLE_ZFSPOOL}/${BASTILLE_PREFIXZFS}" >/dev/null 2>&1; then + info "Dataset ${BASTILLE_ZFSPOOL}/${BASTILLE_PREFIXZFS} already exist, skipping." + else + if ! zfs create -p "${bastille_zfs_options}" -o mountpoint="${bastille_prefix}" "${BASTILLE_ZFSPOOL}/${BASTILLE_PREFIXZFS}"; then + error_exit "Failed to create 'bastille_prefix' dataset, exiting." + fi + fi + chmod 0750 "${bastille_prefix}" + info "Bastille ZFS storage features has been activated successfully!" + exit 0 +} + +write_zfs_disable() { + # Explicitly disable ZFS in 'bastille_zfs_enable' + sysrc -f "${bastille_config}" bastille_zfs_enable="NO" + info "ZFS has been disabled in bastille configuration successfully!" +} + +write_zfs_enable() { + # Explicitly enable ZFS in 'bastille_zfs_enable' + # Just empty the 'bastille_zfs_enable' variable so the user can re-run the ZFS activation helper. + # Don't put "YES" here as it will trigger the ZFS validation and failing due missing and/or invalid configuration. + sysrc -f "${bastille_config}" bastille_zfs_enable="" + info "ZFS activation helper enabled!" +} + +zfs_initial_activation() { + local _response= + + # Just let the user interactively select the ZFS items manually from a list for the initial activation. + # This should be performed before `bastille bootstrap` as we already know. + info "Initial bastille ZFS activation helper invoked." + #read -p "$(info "Would you like bastille attempt to auto-detect/activate ZFS for you?, (assuming a standard install was performed) [y/N]: ")" _response + read -p "$(info "Would you like to configure the bastille ZFS options interactively? [y/N]: ")" _response + + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + # Assume the user knows what hes/she doing and want to configure ZFS parameters interactively. + configure_zfs_manually + ;; + [Nn]|[Nn][Oo]) + # Assume the user will manually edit the ZFS parameters in the config file. + user_canceled + ;; + *) + input_error + ;; + esac +} + +configure_network() { + local _response + + # Configure bastille loopback network interface. + # This is an initial attempt to make this function interactive, + # however this may be enhanced in the future by advanced contributors in this topic. + info "This will attempt to configure the loopback network interface [${bastille_network_loopback}]." + read -p "$(warn "Would you like to configure the loopback network interface now? [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + # shellcheck disable=SC2104 + break + ;; + [Nn]|[Nn][Oo]) + user_canceled + ;; + *) + input_error + ;; + esac + + info "Configuring ${bastille_network_loopback} loopback interface..." + if ! sysrc -qn cloned_interfaces | grep -qi "lo1"; then + sysrc cloned_interfaces+="lo1" + fi + if ! sysrc -qn ifconfig_lo1_name | grep -qi "${bastille_network_loopback}"; then + sysrc ifconfig_lo1_name="${bastille_network_loopback}" + fi + + info "Bringing up new interface: ${bastille_network_loopback}..." service netif cloneup } configure_vnet() { - info "Configuring bridge interface" - sysrc cloned_interfaces+=bridge1 - sysrc ifconfig_bridge1_name=bastille1 + local _response - info "Bringing up new interface: bastille1" + # This is an initial attempt to make this function interactive, + # however this may be enhanced in the future by advanced contributors in this topic. + info "This will attempt to configure the VNET bridge interface [${bastille_ifbridge_name}]." + read -p "$(warn "Would you like to configure the VNET bridge interface now? [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + # shellcheck disable=SC2104 + break + ;; + [Nn]|[Nn][Oo]) + user_canceled + ;; + *) + input_error + ;; + esac + + info "Configuring bridge interface [${bastille_ifbridge_name}]..." + + if ! sysrc -qn cloned_interfaces | grep -qi "${bastille_ifbridge_name}"; then + sysrc cloned_interfaces+="${bastille_ifbridge_name}" + fi + if ! sysrc -qn ifconfig_bridge1_name | grep -qi "${bastille_ifbridge_name}"; then + sysrc ifconfig_bridge1_name="${bastille_ifbridge_name}" + fi + + info "Bringing up new interface: ${bastille_ifbridge_name}..." service netif cloneup - if [ ! -f /etc/devfs.rules ]; then - info "Creating bastille_vnet devfs.rules" + if [ ! -f "/etc/devfs.rules" ]; then + info "Creating bastille_vnet devfs.rules..." cat << EOF > /etc/devfs.rules +# Auto-generated file from `bastille setup` +# devfs configuration information + [bastille_vnet=13] add include \$devfsrules_hide_all add include \$devfsrules_unhide_basic @@ -73,22 +440,47 @@ add include \$devfsrules_jail add include \$devfsrules_jail_vnet add path 'bpf*' unhide EOF + else + warn "File [/etc/devfs.rules] already exist, skipping." + exit 1 fi + exit 0 } -# Configure pf firewall configure_pf() { -# shellcheck disable=SC2154 -if [ ! -f "${bastille_pf_conf}" ]; then - # shellcheck disable=SC3043 - local ext_if - ext_if=$(netstat -rn | awk '/default/ {print $4}' | head -n1) - info "Determined default network interface: ($ext_if)" - info "${bastille_pf_conf} does not exist: creating..." + local _response + + # Configure the PF firewall. + # This is an initial attempt to make this function interactive, + # however this may be enhanced in the future by advanced contributors in this topic. + info "This will attempt to configure the PF firewall parameters in [${bastille_pf_conf}]." + read -p "$(warn "Would you like to configure the PF firewall parameters now? [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + # shellcheck disable=SC2104 + break + ;; + [Nn]|[Nn][Oo]) + user_canceled + ;; + *) + input_error + ;; + esac + + # shellcheck disable=SC2154 + if [ ! -f "${bastille_pf_conf}" ]; then + # shellcheck disable=SC3043 + local ext_if + ext_if=$(netstat -rn | awk '/default/ {print $4}' | head -n1) + info "Determined default network interface: ($ext_if)" + info "${bastille_pf_conf} does not exist: creating..." + + # Creating pf.conf file. + cat << EOF > "${bastille_pf_conf}" +# Auto-generated file from `bastille setup` +# packet filter configuration file - ## creating pf.conf - cat << EOF > "${bastille_pf_conf}" -## generated by bastille setup ext_if="$ext_if" set block-policy return @@ -104,58 +496,399 @@ pass out quick keep state antispoof for \$ext_if inet pass in inet proto tcp from any to any port ssh flags S/SA keep state EOF - sysrc pf_enable=YES - warn "pf ruleset created, please review ${bastille_pf_conf} and enable it using 'service pf start'." -else - error_exit "${bastille_pf_conf} already exists. Exiting." -fi + + if ! sysrc -qn pf_enable | grep -qi "yes"; then + sysrc pf_enable="YES" + fi + warn "The pf ruleset file has been created, please review '${bastille_pf_conf}' and enable it using 'service pf start'." + else + warn "${bastille_pf_conf} already exists, skipping." + exit 1 + fi + exit 0 } -# Configure ZFS configure_zfs() { - if [ ! "$(kldstat -m zfs)" ]; then - info "ZFS module not loaded; skipping..." + # Attempt to detect and setup either new or an existing bastille ZFS on-disk configuration. + # This is useful for new users to easily activate the bastille ZFS parameters on a standard installation, + # or to recover an existing on-disk ZFS bastille configuration in case the config file has been borked/reset by the user, + # also a config backup will be created each time the config needs to be modified in the following format: bastille.conf.YYYYMMDD-HHMMSS + # Be aware that the users now need to explicitly enable ZFS in the config file due later config file changes, failing to do so + # before initial `bastille bootstrap` will private the user from activating ZFS storage features without manual intervention. + + ZFS_DATASET_DETECT= + BASTILLE_CUSTOM_CONFIG= + BASTILLE_INITIAL_CONFIG= + local _response= + + if ! kldstat -qm zfs; then + warn "Looks like the ZFS module is not loaded." + warn "If this is not a dedicated ZFS system you can ignore this warning." + exit 1 else - ## attempt to determine bastille_zroot from `zpool list` - bastille_zroot=$(zpool list | grep -v NAME | awk '{print $1}') - if [ "$(echo "${bastille_zroot}" | wc -l)" -gt 1 ]; then - error_notify "Error: Multiple ZFS pools available:\n${bastille_zroot}" - error_notify "Set desired pool using \"sysrc -f ${bastille_config} bastille_zfs_zpool=ZPOOL_NAME\"" - error_exit "Don't forget to also enable ZFS using \"sysrc -f ${bastille_config} bastille_zfs_enable=YES\"" + # If the below statement becomes true, will assume that the user do not want ZFS activation at all regardless of the + # host filesystem, or the default configuration file has been changed officially and set to "NO" by default. + if echo "${bastille_zfs_enable}" | grep -qi "no"; then + info "Looks like Bastille ZFS has been disabled in 'bastille.conf', ZFS activation helper disabled." + read -p "$(warn "Would you like to enable the ZFS activation helper now? [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + # Assume the user wants to configure the ZFS parameters. + if config_backup; then + write_zfs_enable + warn "Please run 'bastille setup' again or consult bastille.conf for further configuration." + exit 0 + else + error_exit "Config backup creation failed, exiting." + fi + ;; + [Nn]|[Nn][Oo]) + # Assume the user will manually configure the ZFS parameters, or skip ZFS configuration. + user_canceled + ;; + esac + else + # Attempt to detect if bastille was installed with sane defaults(ports/pkg) and hasn't been bootstrapped yet, + # then offer the user initial ZFS activation option to gain all of the ZFS storage features and benefits. + # This should be performed before `bastille` initial bootstrap because several ZFS datasets will be + # created/configured during the bootstrap process by default. + get_zfs_params + if [ ! -d "${bastille_prefix}" ] && [ -n "${BASTILLE_ZFSPOOL}" ]; then + if [ "${bastille_prefix}" = "${bastille_prefix_default}" ] && [ -z "${BASTILLE_CUSTOM_CONFIG}" ]; then + show_zfs_params + info "Looks like bastille has been installed and hasn't been bootstrapped yet." + read -p "$(warn "Would you like to activate ZFS now to get the features and benefits? [y/N]"): " _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + if [ -n "${BASTILLE_ZFSPOOL}" ]; then + info "Attempting to create a backup file of the current bastille.conf file..." + if config_backup; then + write_zfs_opts + create_zfs_dataset + else + error_exit "Config backup creation failed, exiting." + fi + else + error_exit "Unable to determine the [zroot] pool name, exiting" + fi + ;; + [Nn]|[Nn][Oo]) + info "Looks like you cancelled the ZFS activation." + # Offer the user option to disable ZFS in the configuration file. + # Maybe the user wants to use UFS or ZFS with legacy directories instead. + read -p "$(warn "Would you like to explicitly disable ZFS in the configuration file? [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + if config_backup; then + # Assume the user want to skip ZFS configuration regardless. + write_zfs_disable + exit 0 + else + error_exit "Config backup creation failed, exiting." + fi + ;; + [Nn]|[Nn][Oo]) + # Assume the user will manually configure the ZFS parameters by itself. + user_canceled + ;; + *) + input_error + ;; + esac + ;; + *) + input_error + ;; + esac + else + config_validation + fi + else + if [ -d "${bastille_prefix}" ] && [ -z "${bastille_zfs_enable}" ] && [ -z "${bastille_zfs_zpool}" ] && [ -z "${BASTILLE_CUSTOM_CONFIG}" ] && [ -z "${BASTILLE_UFSBOOT}" ]; then + show_zfs_params + # This section is handy if the user has reset the bastille configuration file after a successful ZFS activation. + info "Looks like bastille has been bootstrapped already, but ZFS options are not configured." + info "Attempting to configure default ZFS options for you..." + if zfs list | grep -qw "${bastille_prefix}"; then + ZFS_DATASET_DETECT="1" + read -p "$(warn "Would you like to auto-configure the detected ZFS parameters now? [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + if config_backup; then + write_zfs_opts + exit 0 + else + error_exit "Config backup creation failed, exiting." + fi + ;; + [Nn]|[Nn][Oo]) + # Assume the user will manually configure the ZFS parameters by itself. + user_canceled + ;; + *) + input_error + ;; + esac + else + if [ -d "${bastille_prefix}" ]; then + if [ ! "$(ls -A ${bastille_prefix})" ]; then + if ! zfs list | grep -qw "${bastille_prefix}"; then + # If the user want to use ZFS he/she need to remove/rename the existing 'bastille_prefix' directory manually. + # We do not want to cause existing data lost at all due end-user errors. + warn "Looks like bastille prefix is not a ZFS dataset, thus ZFS storage options are not required." + warn "Please refer to 'bastille.conf' and/or verify for alreay existing 'bastille_prefix' directory." + read -p "$(warn "Would you like to explicitly disable ZFS in the configuration file so we don't ask again? [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + if config_backup; then + write_zfs_disable + exit 0 + else + error_exit "Config backup creation failed, exiting." + fi + ;; + [Nn]|[Nn][Oo]) + # Assume the user will manually configure the ZFS parameters by itself. + user_canceled + ;; + *) + input_error + ;; + esac + fi + else + error_exit "Looks like 'bastille_prefix' is not a ZFS dataset and is not empty, aborting." + fi + fi + fi + fi + if [ -n "${BASTILLE_CUSTOM_CONFIG}" ]; then + # Attempt to detect an existing on-disk bastille ZFS configuration and let the user interactively select the items manually from a list. + # This should be performed if the user has borked/reset the config file or in the event the setup detected an unusual/customized bastille install. + warn "A custom bastille ZFS configuration has been detected and/or unable to read ZFS configuration properly." + warn "Please refer to 'bastille.conf' config file and/or 'bastille setup -help' for additional info." + zfs_initial_activation + else + config_validation + fi + fi fi - sysrc -f "${bastille_config}" bastille_zfs_enable=YES - sysrc -f "${bastille_config}" bastille_zfs_zpool="${bastille_zroot}" fi } -# Run all base functions (w/o vnet) if no args -if [ $# -eq 0 ]; then - sysrc bastille_enable=YES - configure_network - configure_pf - configure_zfs -fi +configure_zfs_manually() { + BASTILLE_CONFIG_USER= + local ZFSPOOL_COUNT="0" + local ZFSDATA_COUNT="0" + local MPREFIX_COUNT="0" + local _zfsprefix_trim= + local _zfspool_choice= + local _zfspool_select= + local _zfsprefix_choice= + local _zfsprefix_select= + local _zfsmount_choice= + local _zfsmount_select= + local _response= -# Handle special-case commands first. -case "$1" in -help|-h|--help) - usage - ;; -pf|firewall) - configure_pf - ;; -bastille0) - # TODO remove in future release 0.13 - warn "'bastille setup bastille0' will be deprecated in the next 0.13 version." - configure_network - ;; -network|loopback) - configure_network - ;; -zfs|storage) - configure_zfs - ;; -bastille1|vnet|bridge) - configure_vnet - ;; + read -p "$(info "Would you like to configure the ZFS parameters entirely by hand? [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + # We will assume the user knows what hes/she doing and want to configure ZFS parameters entirely by hand. + read -p "$(warn "Please enter the desired ZFS pool for bastille: ")" _zfspool_select + read -p "$(warn "Please enter the ZFS dataset for bastille: ")" _zfsprefix_select + read -p "$(warn "Please enter the ZFS mountpoint for bastille: ")" _zfsmount_select + + # Set the parameters and show the user a preview. + BASTILLE_PREFIXDEF="${_zfsmount_select}" + BASTILLE_ZFSPOOL="${_zfspool_select}" + BASTILLE_PREFIXZFS="${_zfsprefix_select}" + show_zfs_params + + # Ask again to make sure the user is confident with the entered parameters. + warn "Are you sure the above bastille ZFS configuration is correct?" + read -p "$(warn "Once bastille is activated it can't be easily undone, do you really want to activate ZFS now? [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + BASTILLE_CONFIG_USER="1" + write_zfs_opts + create_zfs_dataset + ;; + [Nn]|[Nn][Oo]) + user_canceled + ;; + *) + input_error + ;; + esac + ;; + [Nn]|[Nn][Oo]) + # shellcheck disable=SC2104 + break + ;; + *) + input_error + ;; + esac + + # Ask here several times as we want the user to be really sure of what they doing, + # We do not want to cause existing data lost at all due end-user errors. + info "Listing available ZFS pools..." + bastille_zpool=$(zpool list -H | awk '{print $1}') + for _zpool in ${bastille_zpool}; do + echo "[${ZFSPOOL_COUNT}] ${_zpool}" + ZFSPOOL_NUM="${ZFSPOOL_NUM} [${ZFSPOOL_COUNT}]${_zpool}" + ZFSPOOL_COUNT=$(expr ${ZFSPOOL_COUNT} + 1) + done + + read -p "$(info "Please select the ZFS pool [NUM] for bastille: ")" _zfspool_choice + if ! echo "${_zfspool_choice}" | grep -Eq "^[0-9]{1,3}$"; then + error_exit "Invalid input number, aborting!" + else + _zfspool_select=$(echo "${ZFSPOOL_NUM}" | grep -wo "\[${_zfspool_choice}\][^ ]*" | sed 's/\[.*\]//g') + # If the user is unsure here, just abort as no input validation will be performed after. + if [ -z "${_zfspool_select}" ]; then + error_exit "No ZFS pool selected, aborting!" + else + info "Selected ZFS pool: [${_zfspool_select}]" + # Ask again to make sure the user is confident in his election. + read -p "$(warn "Are you sure '${_zfspool_select}' is the correct ZFS pool [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + # shellcheck disable=SC2104 + continue + ;; + [Nn]|[Nn][Oo]) + user_canceled + ;; + *) + input_error + ;; + esac + fi + fi + + # Ask on what zfs dataset `bastille` is installed. + info "Listing available ZFS datasets from the selected ZFS pool..." + bastille_zprefix=$(zfs list -H -r "${_zfspool_select}" | awk '{print $1}') + for _zprefix in ${bastille_zprefix}; do + echo "[${ZFSDATA_COUNT}] ${_zprefix}" + ZFSDATA_NUM="${ZFSDATA_NUM} [${ZFSDATA_COUNT}]${_zprefix}" + ZFSDATA_COUNT=$(expr ${ZFSDATA_COUNT} + 1) + done + read -p "$(info "Please select the ZFS dataset [NUM] for bastille: ")" _zfsprefix_choice + if ! echo "${_zfsprefix_choice}" | grep -Eq "^[0-9]{1,3}$"; then + error_exit "Invalid input number, aborting!" + else + _zfsprefix_select=$(echo "${ZFSDATA_NUM}" | grep -wo "\[${_zfsprefix_choice}\][^ ]*" | sed 's/\[.*\]//g') + if [ -z "${_zfsprefix_select}" ]; then + # If the user is unsure here, just abort as no input validation will be performed after. + error_exit "No ZFS dataset selected, aborting!" + else + _zfsprefix_select=$(echo ${ZFSDATA_NUM} | grep -wo "\[${_zfsprefix_choice}\][^ ]*" | sed 's/\[.*\]//g') + _zfsprefix_trim=$(echo ${ZFSDATA_NUM} | grep -wo "\[${_zfsprefix_choice}\][^ ]*" | awk -F "${_zfspool_select}/" 'NR==1{print $2}') + info "Selected ZFS prefix: [${_zfsprefix_select}]" + # Ask again to make sure the user is confident in his election. + read -p "$(warn "Are you sure '${_zfsprefix_select}' is the correct ZFS dataset [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + # shellcheck disable=SC2104 + continue + ;; + [Nn]|[Nn][Oo]) + user_canceled + ;; + *) + input_error + ;; + esac + fi + fi + + _zfsmount_select="${_zfsprefix_select}" + # Ask what zfs mountpoint `bastille` will use. + info "Listing ZFS mountpoints from the selected ZFS dataset: [${_zfsmount_select}]..." + bastille_prefix=$(zfs list -H "${_zfsmount_select}" | awk '{print $5}') + for _zfsmount_choice in ${bastille_prefix}; do + echo "[${MPREFIX_COUNT}] ${_zfsmount_choice}" + MPREFIX_NUM="${MPREFIX_NUM} [${MPREFIX_COUNT}]${_zfsmount_choice}" + MPREFIX_COUNT=$(expr ${MPREFIX_COUNT} + 1) + done + read -p "$(info "Please select the ZFS mountpoint [NUM] for bastille: ")" _zfsmount_choice + if ! echo "${_zfsmount_choice}" | grep -Eq "^[0-9]{1,3}$"; then + error_exit "Invalid input number, aborting!" + else + _zfsmount_select=$(echo ${MPREFIX_NUM} | grep -wo "\[${_zfsmount_choice}\][^ ]*" | sed 's/\[.*\]//g') + if [ -z "${_zfsmount_select}" ]; then + # If the user is unsure here, just abort as no input validation will be performed after. + error_exit "No ZFS mountpoint selected, aborting!" + else + info "Selected bastille storage mountpoint: [${_zfsmount_select}]" + # Ask again to make sure the user is confident in his election. + read -p "$(warn "Are you sure '${_zfsmount_select}' is the correct bastille prefix [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + # Set the parameters and show the user a preview. + BASTILLE_PREFIXDEF="${_zfsmount_select}" + BASTILLE_ZFSPOOL="${_zfspool_select}" + BASTILLE_PREFIXZFS="${_zfsprefix_trim}" + show_zfs_params + warn "Are you sure the above bastille ZFS configuration is correct?" + read -p "$(warn "Once bastille is activated it can't be easily undone, do you really want to activate ZFS now? [y/N]: ")" _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + write_zfs_opts + create_zfs_dataset + ;; + [Nn]|[Nn][Oo]) + user_canceled + ;; + *) + input_error + ;; + esac + ;; + [Nn]|[Nn][Oo]) + user_canceled + ;; + *) + input_error + ;; + esac + fi + fi + +} + +# Runtime required variables. +config_runtime + +# Handle options one at a time per topic, we don't want users to select/process +# multiple options at once just to end with a broked and/or unwanted configuration. +case "${1}" in + --firewall|-p) + configure_pf + ;; + --network|-n|bastille0) + # TODO remove in future release 0.13 + warn "Notice: 'bastille setup bastille0' will be deprecated in the next 0.13 version." + configure_network + ;; + --vnet|-v|bridge) + configure_vnet + ;; + --zfs|-z) + configure_zfs + ;; + --conf-network-reset) + config_network_reset + ;; + --conf-storage-reset) + config_storage_reset + ;; + --conf-restore-clean) + config_restore_global + ;; + *) + usage + ;; esac From 6327d3654b6e3821d5f7e5b319052e30b3232567 Mon Sep 17 00:00:00 2001 From: JRGTH Date: Tue, 21 Jan 2025 06:25:44 -0400 Subject: [PATCH 117/141] Local shellcheck pass using shellcheck version: 0.8.0 --- usr/local/share/bastille/setup.sh | 75 ++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 27 deletions(-) diff --git a/usr/local/share/bastille/setup.sh b/usr/local/share/bastille/setup.sh index bd22d4fa..f4993a15 100644 --- a/usr/local/share/bastille/setup.sh +++ b/usr/local/share/bastille/setup.sh @@ -103,7 +103,8 @@ config_backup() { config_network_reset() { # Restore bastille default network options. warn "Performing Network configuration reset, requested by the user..." - read -p "$(warn "Do you really want to reset 'bastille' network configuration? [y/N]: ")" _response + warn "Do you really want to reset 'bastille' network configuration? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) local VAR_ITEMS="bastille_network_loopback=bastille0 bastille_network_pf_ext_if=ext_if @@ -126,7 +127,8 @@ config_network_reset() { config_storage_reset() { # Restore bastille default ZFS storage options. warn "Performing ZFS configuration reset, requested by the user..." - read -p "$(warn "Do you really want to reset 'bastille' ZFS configuration? [y/N]: ")" _response + warn "Do you really want to reset 'bastille' ZFS configuration? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) local VAR_ITEMS="bastille_zfs_enable= bastille_zfs_zpool= bastille_zfs_prefix=bastille" @@ -155,7 +157,8 @@ config_restore_global() { # Be aware that if the sample configuration file is missing, we can generate a new one, # but that's highly unlikely to happen so will keep the code smaller here. warn "Performing Bastille default configuration restore, requested by the user..." - read -p "$(warn "Do you really want to restore 'bastille' default configuration file and start over? [y/N]: ")" _response + warn "Do you really want to restore 'bastille' default configuration file and start over? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) config_backup @@ -343,9 +346,8 @@ zfs_initial_activation() { # Just let the user interactively select the ZFS items manually from a list for the initial activation. # This should be performed before `bastille bootstrap` as we already know. info "Initial bastille ZFS activation helper invoked." - #read -p "$(info "Would you like bastille attempt to auto-detect/activate ZFS for you?, (assuming a standard install was performed) [y/N]: ")" _response - read -p "$(info "Would you like to configure the bastille ZFS options interactively? [y/N]: ")" _response - + info "Would you like to configure the bastille ZFS options interactively? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) # Assume the user knows what hes/she doing and want to configure ZFS parameters interactively. @@ -368,7 +370,8 @@ configure_network() { # This is an initial attempt to make this function interactive, # however this may be enhanced in the future by advanced contributors in this topic. info "This will attempt to configure the loopback network interface [${bastille_network_loopback}]." - read -p "$(warn "Would you like to configure the loopback network interface now? [y/N]: ")" _response + warn "Would you like to configure the loopback network interface now? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) # shellcheck disable=SC2104 @@ -400,7 +403,8 @@ configure_vnet() { # This is an initial attempt to make this function interactive, # however this may be enhanced in the future by advanced contributors in this topic. info "This will attempt to configure the VNET bridge interface [${bastille_ifbridge_name}]." - read -p "$(warn "Would you like to configure the VNET bridge interface now? [y/N]: ")" _response + warn "Would you like to configure the VNET bridge interface now? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) # shellcheck disable=SC2104 @@ -454,7 +458,8 @@ configure_pf() { # This is an initial attempt to make this function interactive, # however this may be enhanced in the future by advanced contributors in this topic. info "This will attempt to configure the PF firewall parameters in [${bastille_pf_conf}]." - read -p "$(warn "Would you like to configure the PF firewall parameters now? [y/N]: ")" _response + warn "Would you like to configure the PF firewall parameters now? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) # shellcheck disable=SC2104 @@ -518,7 +523,6 @@ configure_zfs() { ZFS_DATASET_DETECT= BASTILLE_CUSTOM_CONFIG= - BASTILLE_INITIAL_CONFIG= local _response= if ! kldstat -qm zfs; then @@ -530,7 +534,8 @@ configure_zfs() { # host filesystem, or the default configuration file has been changed officially and set to "NO" by default. if echo "${bastille_zfs_enable}" | grep -qi "no"; then info "Looks like Bastille ZFS has been disabled in 'bastille.conf', ZFS activation helper disabled." - read -p "$(warn "Would you like to enable the ZFS activation helper now? [y/N]: ")" _response + warn "Would you like to enable the ZFS activation helper now? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) # Assume the user wants to configure the ZFS parameters. @@ -557,7 +562,8 @@ configure_zfs() { if [ "${bastille_prefix}" = "${bastille_prefix_default}" ] && [ -z "${BASTILLE_CUSTOM_CONFIG}" ]; then show_zfs_params info "Looks like bastille has been installed and hasn't been bootstrapped yet." - read -p "$(warn "Would you like to activate ZFS now to get the features and benefits? [y/N]"): " _response + warn "Would you like to activate ZFS now to get the features and benefits? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) if [ -n "${BASTILLE_ZFSPOOL}" ]; then @@ -576,7 +582,8 @@ configure_zfs() { info "Looks like you cancelled the ZFS activation." # Offer the user option to disable ZFS in the configuration file. # Maybe the user wants to use UFS or ZFS with legacy directories instead. - read -p "$(warn "Would you like to explicitly disable ZFS in the configuration file? [y/N]: ")" _response + warn "Would you like to explicitly disable ZFS in the configuration file? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) if config_backup; then @@ -611,7 +618,8 @@ configure_zfs() { info "Attempting to configure default ZFS options for you..." if zfs list | grep -qw "${bastille_prefix}"; then ZFS_DATASET_DETECT="1" - read -p "$(warn "Would you like to auto-configure the detected ZFS parameters now? [y/N]: ")" _response + warn "Would you like to auto-configure the detected ZFS parameters now? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) if config_backup; then @@ -637,7 +645,8 @@ configure_zfs() { # We do not want to cause existing data lost at all due end-user errors. warn "Looks like bastille prefix is not a ZFS dataset, thus ZFS storage options are not required." warn "Please refer to 'bastille.conf' and/or verify for alreay existing 'bastille_prefix' directory." - read -p "$(warn "Would you like to explicitly disable ZFS in the configuration file so we don't ask again? [y/N]: ")" _response + warn "Would you like to explicitly disable ZFS in the configuration file so we don't ask again? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) if config_backup; then @@ -690,13 +699,17 @@ configure_zfs_manually() { local _zfsmount_select= local _response= - read -p "$(info "Would you like to configure the ZFS parameters entirely by hand? [y/N]: ")" _response + info "Would you like to configure the ZFS parameters entirely by hand? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) # We will assume the user knows what hes/she doing and want to configure ZFS parameters entirely by hand. - read -p "$(warn "Please enter the desired ZFS pool for bastille: ")" _zfspool_select - read -p "$(warn "Please enter the ZFS dataset for bastille: ")" _zfsprefix_select - read -p "$(warn "Please enter the ZFS mountpoint for bastille: ")" _zfsmount_select + warn "Please enter the desired ZFS pool for bastille: " + read _zfspool_select + warn "Please enter the ZFS dataset for bastille: " + read _zfsprefix_select + warn "Please enter the ZFS mountpoint for bastille: " + read _zfsmount_select # Set the parameters and show the user a preview. BASTILLE_PREFIXDEF="${_zfsmount_select}" @@ -706,7 +719,8 @@ configure_zfs_manually() { # Ask again to make sure the user is confident with the entered parameters. warn "Are you sure the above bastille ZFS configuration is correct?" - read -p "$(warn "Once bastille is activated it can't be easily undone, do you really want to activate ZFS now? [y/N]: ")" _response + warn "Once bastille is activated it can't be easily undone, do you really want to activate ZFS now? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) BASTILLE_CONFIG_USER="1" @@ -740,7 +754,8 @@ configure_zfs_manually() { ZFSPOOL_COUNT=$(expr ${ZFSPOOL_COUNT} + 1) done - read -p "$(info "Please select the ZFS pool [NUM] for bastille: ")" _zfspool_choice + info "Please select the ZFS pool [NUM] for bastille: " + read _zfspool_choice if ! echo "${_zfspool_choice}" | grep -Eq "^[0-9]{1,3}$"; then error_exit "Invalid input number, aborting!" else @@ -751,7 +766,8 @@ configure_zfs_manually() { else info "Selected ZFS pool: [${_zfspool_select}]" # Ask again to make sure the user is confident in his election. - read -p "$(warn "Are you sure '${_zfspool_select}' is the correct ZFS pool [y/N]: ")" _response + warn "Are you sure '${_zfspool_select}' is the correct ZFS pool [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) # shellcheck disable=SC2104 @@ -775,7 +791,8 @@ configure_zfs_manually() { ZFSDATA_NUM="${ZFSDATA_NUM} [${ZFSDATA_COUNT}]${_zprefix}" ZFSDATA_COUNT=$(expr ${ZFSDATA_COUNT} + 1) done - read -p "$(info "Please select the ZFS dataset [NUM] for bastille: ")" _zfsprefix_choice + info "Please select the ZFS dataset [NUM] for bastille: " + read _zfsprefix_choice if ! echo "${_zfsprefix_choice}" | grep -Eq "^[0-9]{1,3}$"; then error_exit "Invalid input number, aborting!" else @@ -788,7 +805,8 @@ configure_zfs_manually() { _zfsprefix_trim=$(echo ${ZFSDATA_NUM} | grep -wo "\[${_zfsprefix_choice}\][^ ]*" | awk -F "${_zfspool_select}/" 'NR==1{print $2}') info "Selected ZFS prefix: [${_zfsprefix_select}]" # Ask again to make sure the user is confident in his election. - read -p "$(warn "Are you sure '${_zfsprefix_select}' is the correct ZFS dataset [y/N]: ")" _response + warn "Are you sure '${_zfsprefix_select}' is the correct ZFS dataset [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) # shellcheck disable=SC2104 @@ -813,7 +831,8 @@ configure_zfs_manually() { MPREFIX_NUM="${MPREFIX_NUM} [${MPREFIX_COUNT}]${_zfsmount_choice}" MPREFIX_COUNT=$(expr ${MPREFIX_COUNT} + 1) done - read -p "$(info "Please select the ZFS mountpoint [NUM] for bastille: ")" _zfsmount_choice + info "Please select the ZFS mountpoint [NUM] for bastille: " + read _zfsmount_choice if ! echo "${_zfsmount_choice}" | grep -Eq "^[0-9]{1,3}$"; then error_exit "Invalid input number, aborting!" else @@ -824,7 +843,8 @@ configure_zfs_manually() { else info "Selected bastille storage mountpoint: [${_zfsmount_select}]" # Ask again to make sure the user is confident in his election. - read -p "$(warn "Are you sure '${_zfsmount_select}' is the correct bastille prefix [y/N]: ")" _response + warn "Are you sure '${_zfsmount_select}' is the correct bastille prefix [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) # Set the parameters and show the user a preview. @@ -833,7 +853,8 @@ configure_zfs_manually() { BASTILLE_PREFIXZFS="${_zfsprefix_trim}" show_zfs_params warn "Are you sure the above bastille ZFS configuration is correct?" - read -p "$(warn "Once bastille is activated it can't be easily undone, do you really want to activate ZFS now? [y/N]: ")" _response + warn "Once bastille is activated it can't be easily undone, do you really want to activate ZFS now? [y/N]: " + read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) write_zfs_opts From 603da3ca8df54a4931daf203baea713f6fbb03f3 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 21 Jan 2025 06:54:06 -0700 Subject: [PATCH 118/141] common: Adjust fstab function --- usr/local/share/bastille/common.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 7db2baf6..583bafb0 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -213,7 +213,9 @@ target_all_jails() { export JAILS } -update_fstab() { +# Moving fstab function to common.sh +# Not in use yet, so keeping the name different +update_fstab_new() { local _oldname="${1}" local _newname="${2}" local _fstab="${bastille_jailsdir}/${_newname}/fstab" From 4c2539dd8d11c7861b5a688b5c24ec63bbaac0c3 Mon Sep 17 00:00:00 2001 From: tschettervictor Date: Tue, 21 Jan 2025 07:41:01 -0700 Subject: [PATCH 119/141] copy: Add jcp for jail to jail copy --- usr/local/share/bastille/cp.sh | 84 +++++--------------------- usr/local/share/bastille/jcp.sh | 102 ++++++++++++++++++++++++++++++++ usr/local/share/bastille/rcp.sh | 97 ++++++++++++++++++++++++++++++ 3 files changed, 215 insertions(+), 68 deletions(-) create mode 100644 usr/local/share/bastille/jcp.sh create mode 100644 usr/local/share/bastille/rcp.sh diff --git a/usr/local/share/bastille/cp.sh b/usr/local/share/bastille/cp.sh index ac6d8c2d..33436b34 100644 --- a/usr/local/share/bastille/cp.sh +++ b/usr/local/share/bastille/cp.sh @@ -34,36 +34,23 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_notify "Usage: bastille cp [option(s)] TARGET SOURCE DESTINATION" + error_notify "Usage: bastille cp [option(s)] TARGET HOST_PATH JAIL_PATH" cat << EOF Options: - -j | --jail Jail mode. Copy files from jail to jail(s). - Syntax: [-j jail:srcpath jail:dstpath] - -r | --reverse Reverse copy files from jail to host. - -q | --quiet Suppress output. - -x | --debug Enable debug mode. + -q | --quiet Suppress output. + -x | --debug Enable debug mode. EOF exit 1 } # Handle options. -JAIL_MODE=0 OPTION="-av" -REVERSE_MODE=0 while [ "$#" -gt 0 ]; do case "${1}" in - -h|--help|help) - usage - ;; - -j|--jail) - JAIL_MODE=1 - shift - ;; - -r|--reverse) - REVERSE_MODE=1 - shift + -h|--help|help) + usage ;; -q|--quiet) OPTION="-a" @@ -76,8 +63,6 @@ while [ "$#" -gt 0 ]; do -*) for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do case ${_opt} in - j) JAIL_MODE=1 ;; - r) REVERSE_MODE=1 ;; q) OPTION="-a" ;; x) enable_debug ;; *) error_exit "Unknown Option: \"${1}\"" ;; @@ -95,55 +80,18 @@ if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then usage fi -if [ "${JAIL_MODE}" -eq 1 ] && [ "${REVERSE_MODE}" -eq 1 ]; then - error_exit "[-j|--jail] cannot be used with [-r|reverse]" -fi - -if [ "${JAIL_MODE}" -eq 1 ]; then - SOURCE_TARGET="$(echo ${1} | awk -F":" '{print $1}')" - SOURCE_PATH="$(echo ${1} | awk -F":" '{print $2}')" - DEST_TARGET="$(echo ${2} | awk -F":" '{print $1}')" - DEST_PATH="$(echo ${2} | awk -F":" '{print $2}')" - set_target_single "${SOURCE_TARGET}" && SOURCE_TARGET="${TARGET}" - set_target "${DEST_TARGET}" && DEST_TARGET="${JAILS}" - for _jail in ${DEST_TARGET}; do - if [ "${_jail}" = "${SOURCE_TARGET}" ]; then - continue - fi - info "[${_jail}]:" - source_path="$(echo ${bastille_jailsdir}/${SOURCE_TARGET}/root/${SOURCE_PATH} | sed 's#//#/#g')" - dest_path="$(echo ${bastille_jailsdir}/${_jail}/root/${DEST_PATH} | sed 's#//#/#g')" - if ! cp "${OPTION}" "${source_path}" "${dest_path}"; then - error_continue "CP failed: ${source_path} -> ${dest_path}" - fi - done - exit -fi - TARGET="${1}" -SOURCE="${2}" -DEST="${3}" +HOST_PATH="${2}" +JAIL_PATH="${3}" bastille_root_check +set_target "${TARGET}" -if [ "${REVERSE_MODE}" -eq 1 ]; then - set_target_single "${TARGET}" - for _jail in ${JAILS}; do - info "[${_jail}]:" - host_path="${DEST}" - jail_path="$(echo ${bastille_jailsdir}/${_jail}/root/${SOURCE} | sed 's#//#/#g')" - if ! cp "${OPTION}" "${jail_path}" "${host_path}"; then - error_exit "RCP failed: ${jail_path} -> ${host_path}" - fi - done -else - set_target "${TARGET}" - for _jail in ${JAILS}; do - info "[${_jail}]:" - host_path="${SOURCE}" - jail_path="$(echo ${bastille_jailsdir}/${_jail}/root/${DEST} | sed 's#//#/#g')" - if ! cp "${OPTION}" "${host_path}" "${jail_path}"; then - error_continue "CP failed: ${host_path} -> ${jail_path}" - fi - done -fi +for _jail in ${JAILS}; do + info "[${_jail}]:" + host_path="${HOST_PATH}" + jail_path="$(echo ${bastille_jailsdir}/${_jail}/root/${JAIL_PATH} | sed 's#//#/#g')" + if ! cp "${OPTION}" "${host_path}" "${jail_path}"; then + error_continue "CP failed: ${host_path} -> ${jail_path}" + fi +done \ No newline at end of file diff --git a/usr/local/share/bastille/jcp.sh b/usr/local/share/bastille/jcp.sh new file mode 100644 index 00000000..bd0e4870 --- /dev/null +++ b/usr/local/share/bastille/jcp.sh @@ -0,0 +1,102 @@ +#!/bin/sh +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright (c) 2018-2025, Christer Edwards +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +. /usr/local/share/bastille/common.sh +. /usr/local/etc/bastille/bastille.conf + +usage() { + error_notify "Usage: bastille jcp [option(s)] SOURCE_JAIL JAIL_PATH DEST_JAIL JAIL_PATH" + cat << EOF + Options: + + -q | --quiet Suppress output. + -x | --debug Enable debug mode. + +EOF + exit 1 +} + +# Handle options. +OPTION="-av" +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -q|--quiet) + OPTION="-a" + shift + ;; + -x|--debug) + enable_debug + shift + ;; + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + q) OPTION="-a" ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" ;; + esac + done + shift + ;; + *) + break + ;; + esac +done + +if [ "$#" -ne 4 ]; then + usage +fi + +SOURCE_TARGET="${1}" +SOURCE_PATH="${2}" +DEST_TARGET="${3}" +DEST_PATH="${4}" + +bastille_root_check +set_target_single "${SOURCE_TARGET}" && SOURCE_TARGET="${TARGET}" +set_target "${DEST_TARGET}" && DEST_TARGET="${JAILS}" + +for _jail in ${DEST_TARGET}; do + if [ "${_jail}" = "${SOURCE_TARGET}" ]; then + continue + else + info "[${_jail}]:" + source_path="$(echo ${bastille_jailsdir}/${SOURCE_TARGET}/root/${SOURCE_PATH} | sed 's#//#/#g')" + dest_path="$(echo ${bastille_jailsdir}/${_jail}/root/${DEST_PATH} | sed 's#//#/#g')" + if ! cp "${OPTION}" "${source_path}" "${dest_path}"; then + error_continue "JCP failed: ${source_path} -> ${dest_path}" + fi +done \ No newline at end of file diff --git a/usr/local/share/bastille/rcp.sh b/usr/local/share/bastille/rcp.sh new file mode 100644 index 00000000..c0828ecb --- /dev/null +++ b/usr/local/share/bastille/rcp.sh @@ -0,0 +1,97 @@ +#!/bin/sh +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright (c) 2018-2025, Christer Edwards +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +. /usr/local/share/bastille/common.sh +. /usr/local/etc/bastille/bastille.conf + +usage() { + error_notify "Usage: bastille rcp [option(s)] TARGET JAIL_PATH HOST_PATH" + cat << EOF + Options: + + -q | --quiet Suppress output. + -x | --debug Enable debug mode. + +EOF + exit 1 +} + +# Handle options. +OPTION="-av" +while [ "$#" -gt 0 ]; do + case "${1}" in + -h|--help|help) + usage + ;; + -q|--quiet) + OPTION="-a" + shift + ;; + -x|--debug) + enable_debug + shift + ;; + -*) + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + q) OPTION="-a" ;; + x) enable_debug ;; + *) error_exit "Unknown Option: \"${1}\"" ;; + esac + done + shift + ;; + *) + break + ;; + esac +done + +if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then + usage +fi + +TARGET="${1}" +JAIL_PATH="${2}" +HOST_PATH="${3}" + +bastille_root_check +set_target_single "${TARGET}" + +info "[${TARGET}]:" + +host_path="${HOST_PATH}" +jail_path="$(echo ${bastille_jailsdir}/${TARGET}/root/${JAIL_PATH} | sed 's#//#/#g')" + +if ! cp "${OPTION}" "${jail_path}" "${host_path}"; then + error_exit "RCP failed: ${jail_path} -> ${host_path}" +fi From 086f4a60a5d727643d0d0d5615706f7889b3beab Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 21 Jan 2025 07:42:41 -0700 Subject: [PATCH 120/141] jcp: Add missing fi --- usr/local/share/bastille/jcp.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/usr/local/share/bastille/jcp.sh b/usr/local/share/bastille/jcp.sh index bd0e4870..fc8cf05e 100644 --- a/usr/local/share/bastille/jcp.sh +++ b/usr/local/share/bastille/jcp.sh @@ -99,4 +99,5 @@ for _jail in ${DEST_TARGET}; do if ! cp "${OPTION}" "${source_path}" "${dest_path}"; then error_continue "JCP failed: ${source_path} -> ${dest_path}" fi + fi done \ No newline at end of file From 708c9c3b4d0e51db81d9bfe86676582ddae39313 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 21 Jan 2025 07:48:09 -0700 Subject: [PATCH 121/141] bastille: Add jcp/rcp to commands --- usr/local/bin/bastille | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index fe651702..e293d69d 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -95,7 +95,7 @@ Available Commands: config Get or set a config value for the targeted container(s). console Console into a running container. convert Convert a Thin container into a Thick container. - cp cp(1) files from host or container to host or targeted container(s). + cp cp(1) files from host to jail(s). create Create a new thin container or a thick container if -T|--thick option specified. destroy Destroy a stopped container or a FreeBSD release. edit Edit container configuration files (advanced). @@ -103,11 +103,13 @@ Available Commands: export Exports a specified container. help Help about any command. htop Interactive process viewer (requires htop). + jcp cp(1) files from a jail to jail(s). import Import a specified container. limits Apply resources limits to targeted container(s). See rctl(8). list List containers (running). mount Mount a volume inside the targeted container(s). pkg Manipulate binary packages within targeted container(s). See pkg(8). + rcp cp(1) files from a jail to host. rdr Redirect host port to container port. rename Rename a container. restart Restart a running container. @@ -163,7 +165,7 @@ version|-v|--version) help|-h|--help) usage ;; -bootstrap|create|cp|destroy|etcupdate|export|htop|import|list|mount|rdr|restart|setup|start|top|umount|update|upgrade|verify) +bootstrap|create|cp|destroy|etcupdate|export|htop|import|jcp|list|mount|rcp|rdr|restart|setup|start|top|umount|update|upgrade|verify) # Nothing "extra" to do for these commands. -- cwells ;; clone|config|cmd|console|convert|edit|limits|pkg|rename|service|stop|sysrc|tags|template|zfs) From 42d1c1305849d51c1ea67f65cbf5561874a4c7dd Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 21 Jan 2025 07:58:56 -0700 Subject: [PATCH 122/141] cp: Allow only 3 arcs --- usr/local/share/bastille/cp.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/cp.sh b/usr/local/share/bastille/cp.sh index 33436b34..0d1b53a1 100644 --- a/usr/local/share/bastille/cp.sh +++ b/usr/local/share/bastille/cp.sh @@ -76,7 +76,7 @@ while [ "$#" -gt 0 ]; do esac done -if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then +if [ "$#" -ne 3 ]; then usage fi From 25cc612f46d8c9eb098efa2579a00f745e67deab Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Tue, 21 Jan 2025 07:59:55 -0700 Subject: [PATCH 123/141] rcp: Allow only 3 args --- usr/local/share/bastille/rcp.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/rcp.sh b/usr/local/share/bastille/rcp.sh index c0828ecb..f3880a0f 100644 --- a/usr/local/share/bastille/rcp.sh +++ b/usr/local/share/bastille/rcp.sh @@ -76,7 +76,7 @@ while [ "$#" -gt 0 ]; do esac done -if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then +if [ "$#" -ne 3 ]; then usage fi From 9c0b600bc59bf2b7eed476edab3e52b5ea426e5f Mon Sep 17 00:00:00 2001 From: tschettervictor Date: Tue, 21 Jan 2025 08:14:09 -0700 Subject: [PATCH 124/141] docs: Document new jcp command --- docs/chapters/subcommands/cp.rst | 2 +- docs/chapters/subcommands/jcp.rst | 30 ++++++++++++++++++++++++++++++ docs/chapters/subcommands/rcp.rst | 22 ++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 docs/chapters/subcommands/jcp.rst create mode 100644 docs/chapters/subcommands/rcp.rst diff --git a/docs/chapters/subcommands/cp.rst b/docs/chapters/subcommands/cp.rst index e551fb92..57b610b9 100644 --- a/docs/chapters/subcommands/cp.rst +++ b/docs/chapters/subcommands/cp.rst @@ -2,7 +2,7 @@ cp == -This command allows efficiently copying files from host to container(s). +This command allows copying files from host to jail(s). .. code-block:: shell diff --git a/docs/chapters/subcommands/jcp.rst b/docs/chapters/subcommands/jcp.rst new file mode 100644 index 00000000..fbaeee05 --- /dev/null +++ b/docs/chapters/subcommands/jcp.rst @@ -0,0 +1,30 @@ +=== +jcp +=== + +This command allows copying files from jail to jail(s). + +.. code-block:: shell + + ishmael ~ # bastille cp bastion /tmp/resolv.conf-cf ALL /etc/resolv.conf + [unbound0]: + /usr/local/bastille/jails/bastion/root/tmp/resolv.conf-cf -> /usr/local/bastille/jails/unbound0/root/etc/resolv.conf + [unbound1]: + /usr/local/bastille/jails/bastion/root/tmp/resolv.conf-cf -> /usr/local/bastille/jails/unbound1/root/etc/resolv.conf + [squid]: + /usr/local/bastille/jails/bastion/root/tmp/resolv.conf-cf -> /usr/local/bastille/jails/squid/root/etc/resolv.conf + [nginx]: + /usr/local/bastille/jails/bastion/root/tmp/resolv.conf-cf -> /usr/local/bastille/jails/nginx/root/etc/resolv.conf + [folsom]: + /usr/local/bastille/jails/bastion/root/tmp/resolv.conf-cf -> /usr/local/bastille/jails/folsom/root/etc/resolv.conf + +Unless you see errors reported in the output the `jcp` was successful. + +.. code-block:: shell + + ishmael ~ # bastille cp help + Usage: bastille jcp [option(s)] SOURCE_JAIL JAIL_PATH DEST_JAIL JAIL_PATH + Options: + + -q | --quiet Suppress output. + -x | --debug Enable debug mode. diff --git a/docs/chapters/subcommands/rcp.rst b/docs/chapters/subcommands/rcp.rst new file mode 100644 index 00000000..fd4ab86f --- /dev/null +++ b/docs/chapters/subcommands/rcp.rst @@ -0,0 +1,22 @@ +=== +rcp +=== + +This command allows copying files from jail to host. + +.. code-block:: shell + + ishmael ~ # bastille rcp bastion /test/testfile.txt /tmp/testfile.txt + [bastion]: + /usr/local/bastille/jails/bastion/root/test/testfile.txt -> /tmp/testfile.txt + +Unless you see errors reported in the output the `rcp` was successful. + +.. code-block:: shell + + ishmael ~ # bastille rcp help + Usage: bastille rcp [option(s)] TARGET JAIL_PATH HOST_PATH + Options: + + -q | --quiet Suppress output. + -x | --debug Enable debug mode. From 848bec5fae898dcc6c77cf6a93b29ba22d82ae21 Mon Sep 17 00:00:00 2001 From: JRGTH Date: Tue, 21 Jan 2025 18:17:12 -0400 Subject: [PATCH 125/141] Add --ethernet option for bastille_network_shared Add '-e|--ethernet' option to configure `bastille_network_shared` physical interface, also add config backups to select partial variable resets as well. --- usr/local/share/bastille/setup.sh | 82 +++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/setup.sh b/usr/local/share/bastille/setup.sh index f4993a15..6069f4c0 100644 --- a/usr/local/share/bastille/setup.sh +++ b/usr/local/share/bastille/setup.sh @@ -51,6 +51,7 @@ usage() { -p | --firewall -- Attempt to configure bastille PF firewall. -n | --network -- Attempt to configure network loopback interface. + -e | --ethernet -- Attempt to configure the network shared interface. -v | --vnet -- Attempt to configure VNET bridge interface [bastille1]. -z | --zfs -- Activates ZFS storage features and benefits for bastille. --conf-network-reset -- Restore bastille default Network options on the config file. @@ -107,6 +108,7 @@ config_network_reset() { read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) + config_backup local VAR_ITEMS="bastille_network_loopback=bastille0 bastille_network_pf_ext_if=ext_if bastille_network_pf_table=jails bastille_network_shared= bastille_network_gateway= bastille_network_gateway6=" for _item in ${VAR_ITEMS}; do @@ -131,6 +133,7 @@ config_storage_reset() { read _response case "${_response}" in [Yy]|[Yy][Ee][Ss]) + config_backup local VAR_ITEMS="bastille_zfs_enable= bastille_zfs_zpool= bastille_zfs_prefix=bastille" for _item in ${VAR_ITEMS}; do sysrc -f "${bastille_config}" ${_item} @@ -363,6 +366,76 @@ zfs_initial_activation() { esac } +configure_ethernet() { + # This will attempt to configure the physical ethernet interface for 'bastille_network_shared', + # commonly used with shared IP jails and/or simple jail network configurations. + + local ETHIF_COUNT="0" + local _ethernet_choice= + local _response= + + # Try to get a list of the available physical network/ethernet interfaces. + local ETHERNET_PHY_ADAPTERS=$(pciconf -lv | grep 'ethernet' -B4 | grep 'class=0x020000' | awk -F '@' '{print $1}') + if [ -z "${ETHERNET_PHY_ADAPTERS}" ]; then + error_exit "Unable to detect for any physical ethernet interfaces, exiting." + fi + + info "This will attempt to configure the physical ethernet interface for [bastille_network_shared]." + warn "Would you like to configure the physical ethernet interface now? [y/N]: " + read _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + # shellcheck disable=SC2104 + break + ;; + [Nn]|[Nn][Oo]) + user_canceled + ;; + *) + input_error + ;; + esac + + info "Listing available physical ethernet interfaces..." + for _ethernetif in ${ETHERNET_PHY_ADAPTERS}; do + echo "[${ETHIF_COUNT}] ${_ethernetif}" + ETHIF_NUM="${ETHIF_NUM} [${ETHIF_COUNT}]${_ethernetif}" + ETHIF_COUNT=$(expr ${ETHIF_COUNT} + 1) + done + + info "Please select the wanted physical ethernet adapter [NUM] to be used as 'bastille_network_shared': " + read _ethernet_choice + if ! echo "${_ethernet_choice}" | grep -Eq "^[0-9]{1,3}$"; then + error_exit "Invalid input number, aborting!" + else + _ethernet_select=$(echo "${ETHIF_NUM}" | grep -wo "\[${_ethernet_choice}\][^ ]*" | sed 's/\[.*\]//g') + # If the user is unsure here, just abort as no input validation will be performed after. + if [ -z "${_ethernet_select}" ]; then + error_exit "No physical ethernet interface selected, aborting!" + else + info "Selected physical ethernet interface: [${_ethernet_select}]" + # Ask again to make sure the user is confident with the election. + warn "Are you sure '${_ethernet_select}' is the correct physical ethernet interface [y/N]: " + read _response + case "${_response}" in + [Yy]|[Yy][Ee][Ss]) + if ! sysrc -f "${bastille_config}" bastille_network_shared | grep -qi "${_ethernet_select}"; then + config_backup + sysrc -f "${bastille_config}" bastille_network_shared="${_ethernet_select}" + fi + exit 0 + ;; + [Nn]|[Nn][Oo]) + user_canceled + ;; + *) + input_error + ;; + esac + fi + fi +} + configure_network() { local _response @@ -765,7 +838,7 @@ configure_zfs_manually() { error_exit "No ZFS pool selected, aborting!" else info "Selected ZFS pool: [${_zfspool_select}]" - # Ask again to make sure the user is confident in his election. + # Ask again to make sure the user is confident with the election. warn "Are you sure '${_zfspool_select}' is the correct ZFS pool [y/N]: " read _response case "${_response}" in @@ -804,7 +877,7 @@ configure_zfs_manually() { _zfsprefix_select=$(echo ${ZFSDATA_NUM} | grep -wo "\[${_zfsprefix_choice}\][^ ]*" | sed 's/\[.*\]//g') _zfsprefix_trim=$(echo ${ZFSDATA_NUM} | grep -wo "\[${_zfsprefix_choice}\][^ ]*" | awk -F "${_zfspool_select}/" 'NR==1{print $2}') info "Selected ZFS prefix: [${_zfsprefix_select}]" - # Ask again to make sure the user is confident in his election. + # Ask again to make sure the user is confident with the election. warn "Are you sure '${_zfsprefix_select}' is the correct ZFS dataset [y/N]: " read _response case "${_response}" in @@ -842,7 +915,7 @@ configure_zfs_manually() { error_exit "No ZFS mountpoint selected, aborting!" else info "Selected bastille storage mountpoint: [${_zfsmount_select}]" - # Ask again to make sure the user is confident in his election. + # Ask again to make sure the user is confident with the election. warn "Are you sure '${_zfsmount_select}' is the correct bastille prefix [y/N]: " read _response case "${_response}" in @@ -889,6 +962,9 @@ case "${1}" in --firewall|-p) configure_pf ;; + --ethernet|-e) + configure_ethernet + ;; --network|-n|bastille0) # TODO remove in future release 0.13 warn "Notice: 'bastille setup bastille0' will be deprecated in the next 0.13 version." From f45fb739134b416c80ddff72ac782873d3ba79a8 Mon Sep 17 00:00:00 2001 From: JRGTH Date: Tue, 21 Jan 2025 18:23:52 -0400 Subject: [PATCH 126/141] Quick shellcheck fix as per suggestion --- usr/local/share/bastille/setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/setup.sh b/usr/local/share/bastille/setup.sh index 6069f4c0..518ec976 100644 --- a/usr/local/share/bastille/setup.sh +++ b/usr/local/share/bastille/setup.sh @@ -375,7 +375,7 @@ configure_ethernet() { local _response= # Try to get a list of the available physical network/ethernet interfaces. - local ETHERNET_PHY_ADAPTERS=$(pciconf -lv | grep 'ethernet' -B4 | grep 'class=0x020000' | awk -F '@' '{print $1}') + local ETHERNET_PHY_ADAPTERS="$(pciconf -lv | grep 'ethernet' -B4 | grep 'class=0x020000' | awk -F '@' '{print $1}')" if [ -z "${ETHERNET_PHY_ADAPTERS}" ]; then error_exit "Unable to detect for any physical ethernet interfaces, exiting." fi From 050d2008322ea7a3a97bee35e5bcfc47680fd02c Mon Sep 17 00:00:00 2001 From: JRGTH Date: Tue, 21 Jan 2025 18:45:38 -0400 Subject: [PATCH 127/141] Quick cleanup revision --- usr/local/share/bastille/setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/setup.sh b/usr/local/share/bastille/setup.sh index 518ec976..8e609d95 100644 --- a/usr/local/share/bastille/setup.sh +++ b/usr/local/share/bastille/setup.sh @@ -372,6 +372,7 @@ configure_ethernet() { local ETHIF_COUNT="0" local _ethernet_choice= + local _ethernet_select= local _response= # Try to get a list of the available physical network/ethernet interfaces. @@ -950,7 +951,6 @@ configure_zfs_manually() { esac fi fi - } # Runtime required variables. From b3ff3efed9918c7708996cbbe93e2c671679cc26 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 24 Jan 2025 06:49:19 -0700 Subject: [PATCH 128/141] common: Add comment about MAC address --- usr/local/share/bastille/common.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 583bafb0..c2017841 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -230,7 +230,9 @@ generate_static_mac() { local jail_name="${1}" local external_interface="${2}" local external_interface_mac="$(ifconfig ${external_interface} | grep ether | awk '{print $2}')" + # Use FreeBSD vendor MAC prefix (58:9c:fc) for jail MAC prefix local macaddr_prefix="58:9c:fc" + # Use hash of interface+jailname for jail MAC suffix local macaddr_suffix="$(echo -n "${external_interface_mac}${jail_name}" | sed 's#:##g' | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" if [ -z "${macaddr_prefix}" ] || [ -z "${macaddr_suffix}" ]; then error_notify "Failed to generate MAC address." From 2c45c51e8412b9ed1e97a07454a8093caf4c5c5e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 24 Jan 2025 07:33:19 -0700 Subject: [PATCH 129/141] common: Add notes about how MAC is generated --- usr/local/share/bastille/common.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 8c7e57e9..6837d76d 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -228,8 +228,9 @@ generate_static_mac() { local jail_name="${1}" local external_interface="${2}" local external_interface_mac="$(ifconfig ${external_interface} | grep ether | awk '{print $2}')" - # Use FreeBSD vendor prefix for jail MAC prefix + # Use FreeBSD vendor MAC prefix (58:9c:fc) for jail MAC prefix local macaddr_prefix="58:9c:fc" + # Use hash of interface+jailname for jail MAC suffix local macaddr_suffix="$(echo -n "${external_interface_mac}${jail_name}" | sed 's#:##g' | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')" if [ -z "${macaddr_prefix}" ] || [ -z "${macaddr_suffix}" ]; then error_notify "Failed to generate MAC address." @@ -364,4 +365,4 @@ checkyesno() { return 1 ;; esac -} \ No newline at end of file +} From 8425524959461d695388b27fb79bbe2dc8714513 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 24 Jan 2025 07:52:22 -0700 Subject: [PATCH 130/141] create: Clarify numbers > digits/numerals --- usr/local/share/bastille/create.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index 9160835f..50383782 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -69,7 +69,7 @@ validate_name() { elif [ "${NAME_VERIFY}" != "${NAME_SANITY}" ]; then error_exit "Container names may not contain special characters!" elif echo "${NAME_VERIFY}" | grep -qE '^[0-9]+$'; then - error_exit "Container names may not contain only numbers." + error_exit "Container names may not contain only digits/numerals." fi } From 94da0c4817fb3a680f2a4da961d010d4bd57a5a9 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Fri, 24 Jan 2025 08:06:39 -0700 Subject: [PATCH 131/141] create: digits/numerals > digits --- usr/local/share/bastille/create.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index 50383782..bfc62d06 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -69,7 +69,7 @@ validate_name() { elif [ "${NAME_VERIFY}" != "${NAME_SANITY}" ]; then error_exit "Container names may not contain special characters!" elif echo "${NAME_VERIFY}" | grep -qE '^[0-9]+$'; then - error_exit "Container names may not contain only digits/numerals." + error_exit "Container names may not contain only digits." fi } From 2f594e4e65c8728141220998f8deb1668eaa5e59 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 25 Jan 2025 10:22:23 -0700 Subject: [PATCH 132/141] common: Also check ifconfig for epairs --- usr/local/share/bastille/common.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 6837d76d..3f861fab 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -247,14 +247,14 @@ generate_vnet_jail_netblock() { ## determine number of interfaces + 1 ## iterate num and grep all jail configs ## define uniq_epair - local _epair_if_count="$(grep -Eos 'epair[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local _epair_if_count="$( (grep -Eos 'epair[0-9]+' ${bastille_jailsdir}/*/jail.conf; ifconfig | grep -Eo '(e[0-9]+a|epair[0-9]+a)' ) | sort -u | wc -l | awk '{print $1}')" local _bastille_if_count="$(grep -Eos 'bastille[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" local epair_num_range=$((_epair_if_count + 1)) local bastille_num_range=$((_bastille_if_count + 1)) if [ -n "${use_unique_bridge}" ]; then if [ "${_epair_if_count}" -gt 0 ]; then for _num in $(seq 0 "${epair_num_range}"); do - if ! grep -Eosq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then + if ! grep -Eosq "epair${_num}" ${bastille_jailsdir}/*/jail.conf && ! ifconfig | grep -Eosq "(e${_num}a|epair${_num}a)"; then if [ "$(echo -n "e${_num}a_${jail_name}" | awk '{print length}')" -lt 16 ]; then local host_epair=e${_num}a_${jail_name} local jail_epair=e${_num}b_${jail_name} From 1a77041e8e88bc0d9c8b6329645e6b08341ab860 Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sat, 25 Jan 2025 10:24:33 -0700 Subject: [PATCH 133/141] clone: Also check ifconfig for epairs --- usr/local/share/bastille/clone.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index 9c945f94..998f4674 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -181,14 +181,14 @@ update_jailconf_vnet() { # Determine number of interfaces and define a uniq_epair local _if_list="$(grep -Eo 'epair[0-9]+|bastille[0-9]+' ${_jail_conf} | sort -u)" for _if in ${_if_list}; do - local _epair_if_count="$(grep -Eo 'epair[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" + local _epair_if_count="$( (grep -Eo 'epair[0-9]+' ${bastille_jailsdir}/*/jail.conf; ifconfig | grep -Eo '(e[0-9]+a|epair[0-9]+a)' ) | sort -u | wc -l | awk '{print $1}')" local _bastille_if_count="$(grep -Eo 'bastille[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')" local epair_num_range=$((_epair_if_count + 1)) local bastille_num_range=$((_bastille_if_count + 1)) if echo ${_if} | grep -Eoq 'epair[0-9]+'; then # Update bridged VNET config for _num in $(seq 0 "${epair_num_range}"); do - if ! grep -oq "epair${_num}" ${bastille_jailsdir}/*/jail.conf; then + if ! grep -Eoq "epair${_num}" ${bastille_jailsdir}/*/jail.conf && ! ifconfig | grep -Eoq "(e${_num}a|epair${_num}a)"; then # Generate new epair name if [ "$(echo -n "e${_num}a_${NEWNAME}" | awk '{print length}')" -lt 16 ]; then local _new_host_epair="e${_num}a_${NEWNAME}" From b1d6b49141b5bec828e092dd36065b9ead4c4bbf Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 26 Jan 2025 11:11:00 -0700 Subject: [PATCH 134/141] clone: Typo in usage block --- usr/local/share/bastille/clone.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index 998f4674..2d2dee9e 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -39,7 +39,7 @@ usage() { Options: -a | --auto Auto mode. Start/stop jail(s) if required. Cannot be used with [-l|--live]. - -l | --live Clone a running jail. ZFS only. Jail must be running. Cannot be used with [-f|--force]. + -l | --live Clone a running jail. ZFS only. Jail must be running. Cannot be used with [-a|--auto]. -x | --debug Enable debug mode. EOF From fe1eb18fbdf803c3ad4b7e2e82fac2539483390e Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 26 Jan 2025 12:53:49 -0700 Subject: [PATCH 135/141] docs: Typo in jcp --- docs/chapters/subcommands/jcp.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/chapters/subcommands/jcp.rst b/docs/chapters/subcommands/jcp.rst index fbaeee05..6dca3c3d 100644 --- a/docs/chapters/subcommands/jcp.rst +++ b/docs/chapters/subcommands/jcp.rst @@ -6,7 +6,7 @@ This command allows copying files from jail to jail(s). .. code-block:: shell - ishmael ~ # bastille cp bastion /tmp/resolv.conf-cf ALL /etc/resolv.conf + ishmael ~ # bastille jcp bastion /tmp/resolv.conf-cf ALL /etc/resolv.conf [unbound0]: /usr/local/bastille/jails/bastion/root/tmp/resolv.conf-cf -> /usr/local/bastille/jails/unbound0/root/etc/resolv.conf [unbound1]: @@ -22,7 +22,7 @@ Unless you see errors reported in the output the `jcp` was successful. .. code-block:: shell - ishmael ~ # bastille cp help + ishmael ~ # bastille jcp help Usage: bastille jcp [option(s)] SOURCE_JAIL JAIL_PATH DEST_JAIL JAIL_PATH Options: From bcf738b6eef71bf2939a6647056126000e24964e Mon Sep 17 00:00:00 2001 From: Juan David Hurtado G Date: Sun, 26 Jan 2025 20:45:37 -0500 Subject: [PATCH 136/141] Revert "Merge pull request #823 from JRGTH/bastille_setup_initial" This reverts commit acc7bb9739d67e781b6f9c830c0e29f9cd84de63, reversing changes made to 05dc2b8d6a371ce3930ce502150293c18d7d1bea. --- usr/local/share/bastille/setup.sh | 974 +++--------------------------- 1 file changed, 72 insertions(+), 902 deletions(-) diff --git a/usr/local/share/bastille/setup.sh b/usr/local/share/bastille/setup.sh index 8e609d95..020d2cf4 100644 --- a/usr/local/share/bastille/setup.sh +++ b/usr/local/share/bastille/setup.sh @@ -1,5 +1,7 @@ #!/bin/sh # +# SPDX-License-Identifier: BSD-3-Clause +# # Copyright (c) 2018-2025, Christer Edwards # All rights reserved. # @@ -28,488 +30,41 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# Let's set some predefined/fallback variables. -bastille_config_path="/usr/local/etc/bastille" -bastille_config="${bastille_config_path}/bastille.conf" -bastille_prefix_default="/usr/local/bastille" -bastille_zfsprefix_default="bastille" -bastille_ifbridge_name="bastille1" - +bastille_config="/usr/local/etc/bastille/bastille.conf" . /usr/local/share/bastille/common.sh # shellcheck source=/usr/local/etc/bastille/bastille.conf . ${bastille_config} usage() { - # Build an independent usage for the `setup` command. - # No short options here for the special purpose --long-options, - # so we can reserve short options for future adds, also the user - # must genuinely agreed on configuration reset/restore so let them type for it. - error_notify "Usage: bastille setup [option]" - - cat << EOF - Options: - - -p | --firewall -- Attempt to configure bastille PF firewall. - -n | --network -- Attempt to configure network loopback interface. - -e | --ethernet -- Attempt to configure the network shared interface. - -v | --vnet -- Attempt to configure VNET bridge interface [bastille1]. - -z | --zfs -- Activates ZFS storage features and benefits for bastille. - --conf-network-reset -- Restore bastille default Network options on the config file. - --conf-storage-reset -- Restore bastille default ZFS storage options on the config file. - --conf-restore-clean -- Restore bastille default config file from bastille.conf.sample file. - -EOF - exit 1 + error_exit "Usage: bastille setup [pf|network|zfs|vnet]" } -input_error() { - error_exit "Invalid user input, aborting!" -} - -config_runtime() { - # Run here variables considered to be required by bastille by default silently. - if ! sysrc -qn bastille_enable | grep -qi "yes"; then - sysrc bastille_enable="YES" >/dev/null 2>&1 - fi -} - -# Check for too many args. +# Check for too many args if [ $# -gt 1 ]; then usage fi -# Handle special-case commands first. -case "${1}" in - help|--help|-h) - usage - ;; -esac - -user_canceled() { - # Don't use 'error_exit' here as this only should inform the user, not panic them. - info "Cancelled by user, exiting!" - exit 1 -} - -config_backup() { - # Create bastille configuration backup with system time appended. - # This should be called each time `bastille setup` attempts to - # write to bastille configuration file. - BACKUP_DATE=$(date +%Y%m%d-%H%M%S) - cp "${bastille_config}" "${bastille_config}.${BACKUP_DATE}" - BACKUP_NAME="${bastille_config}.${BACKUP_DATE}" - info "Config backup created in: [${BACKUP_NAME}]" -} - -config_network_reset() { - # Restore bastille default network options. - warn "Performing Network configuration reset, requested by the user..." - warn "Do you really want to reset 'bastille' network configuration? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - config_backup - local VAR_ITEMS="bastille_network_loopback=bastille0 bastille_network_pf_ext_if=ext_if - bastille_network_pf_table=jails bastille_network_shared= bastille_network_gateway= bastille_network_gateway6=" - for _item in ${VAR_ITEMS}; do - sysrc -f "${bastille_config}" ${_item} - done - info "Network configuration has been reset successfully!" - exit 0 - ;; - [Nn]|[Nn][Oo]) - user_canceled - ;; - *) - input_error - ;; - esac -} - -config_storage_reset() { - # Restore bastille default ZFS storage options. - warn "Performing ZFS configuration reset, requested by the user..." - warn "Do you really want to reset 'bastille' ZFS configuration? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - config_backup - local VAR_ITEMS="bastille_zfs_enable= bastille_zfs_zpool= bastille_zfs_prefix=bastille" - for _item in ${VAR_ITEMS}; do - sysrc -f "${bastille_config}" ${_item} - done - - # Let's configure variables with complex values individually to keep it simple/readable for everyone. - sysrc -f "${bastille_config}" bastille_zfs_options="-o compress=lz4 -o atime=off" - sysrc -f "${bastille_config}" bastille_prefix="${bastille_prefix_default}" - info "ZFS configuration has been reset successfully!" - exit 0 - ;; - [Nn]|[Nn][Oo]) - user_canceled - ;; - *) - input_error - ;; - esac -} - -config_restore_global() { - local _response - # This will restore bastille default configuration file from the sample config file. - # Be aware that if the sample configuration file is missing, we can generate a new one, - # but that's highly unlikely to happen so will keep the code smaller here. - warn "Performing Bastille default configuration restore, requested by the user..." - warn "Do you really want to restore 'bastille' default configuration file and start over? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - config_backup - if [ -f "${bastille_config}.sample" ]; then - mv "${bastille_config}" "${bastille_config}.${BACKUP_DATE}" - cp "${bastille_config}.sample" "${bastille_config}" - else - error_exit "Bastille sample configuration file is missing, exiting." - fi - info "Bastille configuration file restored successfully!" - exit 0 - ;; - [Nn]|[Nn][Oo]) - user_canceled - ;; - *) - input_error - ;; - esac -} - -get_zfs_params() { - info "Reading on-disk and bastille ZFS config parameters..." - # Always try to detect and recover on-disk ZFS bastille configuration first. - # Bastille ZFS prefix is always set to "bastille" in the config file by default, - # so will keep things simple here, or considered custom setup if this variable is changed. - BARTILLE_ROOTFS=$(mount | awk '/ \/ / {print $1}') - BASTILLE_UFSBOOT= - BASTILLE_ZFSPOOL= - BASTILLE_PREFIXDEF= - BASTILLE_ZFSENABLE= - BASTILLE_PREFIX_MATCH= - - # Check if the system boots from ZFS. - if echo "${BARTILLE_ROOTFS}" | grep -q -m 1 -E "^/dev/"; then - # Assume the host is running from UFS. - info "This system doesn't boot from ZFS, looking for alternate configuration." - BASTILLE_UFSBOOT="1" - fi - - BASTILLE_PREFIXCONF=$(sysrc -qn -f "${bastille_config}" bastille_prefix) - BASTILLE_PREFIXZFS=$(sysrc -qn -f "${bastille_config}" bastille_zfs_prefix) - - if [ -z "${BASTILLE_PREFIXZFS}" ]; then - BASTILLE_PREFIXZFS="${bastille_zfsprefix_default}" - fi - - if [ -z "${BASTILLE_UFSBOOT}" ]; then - if [ "${BASTILLE_PREFIXZFS}" != "${bastille_zfsprefix_default}" ]; then - BASTILLE_CUSTOM_CONFIG="1" - fi - fi - - # Try to determine "zroot" pool name as it may happens that the user - # customized the "zroot" pool name during the initial FreeBSD installation. - if [ -z "${BASTILLE_UFSBOOT}" ]; then - #BASTILLE_ZFSPOOL=$(df ${bastille_config_path} 2>/dev/null | sed 1d | awk -F '/' '{print $1}') - BASTILLE_ZFSPOOL=$(zfs list -H ${bastille_config_path} 2>/dev/null | awk -F '/' '{print $1}') - fi - - if [ -z "${BASTILLE_UFSBOOT}" ]; then - BASTILLE_PREFIXDEF=$(zfs list -H "${BASTILLE_ZFSPOOL}/${BASTILLE_PREFIXZFS}" 2>/dev/null | awk '{print $5}') - fi - - if [ -n "${BASTILLE_UFSBOOT}" ]; then - # Make sure bastille_prefix is listed by ZFS then try to get bastille_zfs_pool from it. - # Make some additional checks for non ZFS boot systems, also rely on some 'bastille.conf' ZFS parameters. - BASTILLE_PREFIXLOOK=$(zfs list -H "${BASTILLE_PREFIXCONF}" 2>/dev/null | awk '{print $1}') - BASTILLE_ZFSPOOL=$(zfs list -H "${BASTILLE_PREFIXLOOK}" 2>/dev/null | awk -F '/' '{print $1}') - BASTILLE_PREFIXDEF=$(zfs list -H "${BASTILLE_PREFIXCONF}" 2>/dev/null | awk '{print $5}') - - else - # Fallback to default config. - if [ -z "${BASTILLE_PREFIXDEF}" ]; then - BASTILLE_PREFIXDEF="${bastille_prefix_default}" - fi - fi - - if [ "${BASTILLE_PREFIXDEF}" = "${BASTILLE_PREFIXCONF}" ]; then - BASTILLE_PREFIX_MATCH="1" - fi - - # Update 'bastille_prefix' if a custom dataset is detected while reading on-disk configuration. - if [ ! -d "${bastille_prefix}" ] || [ -n "${ZFS_DATASET_DETECT}" ] || [ -n "${BASTILLE_PREFIXDEF}" ]; then - BASTILLE_ZFSENABLE="YES" - bastille_prefix="${BASTILLE_PREFIXDEF}" - else - BASTILLE_ZFSENABLE="NO" - if [ -z "${BASTILLE_UFSBOOT}" ]; then - BASTILLE_PREFIXZFS="" - fi - fi -} - -config_validation(){ - # Perform a basic bastille ZFS configuration check, - if [ -d "${bastille_prefix}" ] && [ -n "${BASTILLE_PREFIX_MATCH}" ] && echo "${bastille_zfs_enable}" | grep -qi "yes" \ - && zfs list "${bastille_zfs_zpool}/${bastille_zfs_prefix}" >/dev/null 2>&1; then - info "Looks like Bastille ZFS storage features has been activated successfully!." - exit 0 - else - if [ ! -d "${bastille_prefix}" ] && [ -z "${BASTILLE_ZFSPOOL}" ]; then - zfs_initial_activation - else - if ! echo "${bastille_zfs_enable}" | grep -qi "no"; then - - # Inform the user bastille ZFS configuration has been tampered and/or on-disk ZFS config has changed. - error_exit "Bastille ZFS misconfiguration detected, please refer to 'bastille.conf' or see 'bastille setup --config-reset'." - fi - fi - fi -} - -show_zfs_params() { - # Show a brief info of the detected and/or pending bastille ZFS configuration parameters. - # Don't need to show bastille zfs enable as this will be enabled by default. - info "*************************************" - info "Bastille Storage Prefix: [${BASTILLE_PREFIXDEF}]" - info "Bastille ZFS Pool: [${BASTILLE_ZFSPOOL}]" - info "Bastille ZFS Prefix: [${BASTILLE_PREFIXZFS}]" - info "*************************************" -} - -write_zfs_opts() { - # Write/update to bastille config file the required and/or misssing parameters. - if [ -z "${bastille_prefix}" ] || [ "${BASTILLE_PREFIXDEF}" != "${bastille_prefix_default}" ]; then - if [ -z "${BASTILLE_PREFIX_MATCH}" ]; then - sysrc -f "${bastille_config}" bastille_prefix="${BASTILLE_PREFIXDEF}" - fi - else - if [ -z "${BASTILLE_PREFIXCONF}" ] && [ -n "${BASTILLE_PREFIXDEF}" ]; then - sysrc -f "${bastille_config}" bastille_prefix="${BASTILLE_PREFIXDEF}" - fi - fi - - if [ -z "${bastille_zfs_enable}" ]; then - sysrc -f "${bastille_config}" bastille_zfs_enable="${BASTILLE_ZFSENABLE}" - fi - if [ -z "${bastille_zfs_zpool}" ]; then - sysrc -f "${bastille_config}" bastille_zfs_zpool="${BASTILLE_ZFSPOOL}" - fi - if [ -z "${bastille_zfs_prefix}" ] || [ "${BASTILLE_PREFIXDEF}" != "${bastille_zfs_prefix}" ]; then - sysrc -f "${bastille_config}" bastille_zfs_prefix="${BASTILLE_PREFIXZFS}" - fi - info "ZFS has been enabled in bastille configuration successfully!" -} - -create_zfs_dataset(){ - info "Creating ZFS dataset [${BASTILLE_ZFSPOOL}/${BASTILLE_PREFIXZFS}] for bastille..." - - if [ -n "${BASTILLE_CONFIG_USER}" ]; then - bastille_prefix="${BASTILLE_PREFIXDEF}" - fi - - # shellcheck disable=SC1073 - if zfs list "${BASTILLE_ZFSPOOL}/${BASTILLE_PREFIXZFS}" >/dev/null 2>&1; then - info "Dataset ${BASTILLE_ZFSPOOL}/${BASTILLE_PREFIXZFS} already exist, skipping." - else - if ! zfs create -p "${bastille_zfs_options}" -o mountpoint="${bastille_prefix}" "${BASTILLE_ZFSPOOL}/${BASTILLE_PREFIXZFS}"; then - error_exit "Failed to create 'bastille_prefix' dataset, exiting." - fi - fi - chmod 0750 "${bastille_prefix}" - info "Bastille ZFS storage features has been activated successfully!" - exit 0 -} - -write_zfs_disable() { - # Explicitly disable ZFS in 'bastille_zfs_enable' - sysrc -f "${bastille_config}" bastille_zfs_enable="NO" - info "ZFS has been disabled in bastille configuration successfully!" -} - -write_zfs_enable() { - # Explicitly enable ZFS in 'bastille_zfs_enable' - # Just empty the 'bastille_zfs_enable' variable so the user can re-run the ZFS activation helper. - # Don't put "YES" here as it will trigger the ZFS validation and failing due missing and/or invalid configuration. - sysrc -f "${bastille_config}" bastille_zfs_enable="" - info "ZFS activation helper enabled!" -} - -zfs_initial_activation() { - local _response= - - # Just let the user interactively select the ZFS items manually from a list for the initial activation. - # This should be performed before `bastille bootstrap` as we already know. - info "Initial bastille ZFS activation helper invoked." - info "Would you like to configure the bastille ZFS options interactively? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - # Assume the user knows what hes/she doing and want to configure ZFS parameters interactively. - configure_zfs_manually - ;; - [Nn]|[Nn][Oo]) - # Assume the user will manually edit the ZFS parameters in the config file. - user_canceled - ;; - *) - input_error - ;; - esac -} - -configure_ethernet() { - # This will attempt to configure the physical ethernet interface for 'bastille_network_shared', - # commonly used with shared IP jails and/or simple jail network configurations. - - local ETHIF_COUNT="0" - local _ethernet_choice= - local _ethernet_select= - local _response= - - # Try to get a list of the available physical network/ethernet interfaces. - local ETHERNET_PHY_ADAPTERS="$(pciconf -lv | grep 'ethernet' -B4 | grep 'class=0x020000' | awk -F '@' '{print $1}')" - if [ -z "${ETHERNET_PHY_ADAPTERS}" ]; then - error_exit "Unable to detect for any physical ethernet interfaces, exiting." - fi - - info "This will attempt to configure the physical ethernet interface for [bastille_network_shared]." - warn "Would you like to configure the physical ethernet interface now? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - # shellcheck disable=SC2104 - break - ;; - [Nn]|[Nn][Oo]) - user_canceled - ;; - *) - input_error - ;; - esac - - info "Listing available physical ethernet interfaces..." - for _ethernetif in ${ETHERNET_PHY_ADAPTERS}; do - echo "[${ETHIF_COUNT}] ${_ethernetif}" - ETHIF_NUM="${ETHIF_NUM} [${ETHIF_COUNT}]${_ethernetif}" - ETHIF_COUNT=$(expr ${ETHIF_COUNT} + 1) - done - - info "Please select the wanted physical ethernet adapter [NUM] to be used as 'bastille_network_shared': " - read _ethernet_choice - if ! echo "${_ethernet_choice}" | grep -Eq "^[0-9]{1,3}$"; then - error_exit "Invalid input number, aborting!" - else - _ethernet_select=$(echo "${ETHIF_NUM}" | grep -wo "\[${_ethernet_choice}\][^ ]*" | sed 's/\[.*\]//g') - # If the user is unsure here, just abort as no input validation will be performed after. - if [ -z "${_ethernet_select}" ]; then - error_exit "No physical ethernet interface selected, aborting!" - else - info "Selected physical ethernet interface: [${_ethernet_select}]" - # Ask again to make sure the user is confident with the election. - warn "Are you sure '${_ethernet_select}' is the correct physical ethernet interface [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - if ! sysrc -f "${bastille_config}" bastille_network_shared | grep -qi "${_ethernet_select}"; then - config_backup - sysrc -f "${bastille_config}" bastille_network_shared="${_ethernet_select}" - fi - exit 0 - ;; - [Nn]|[Nn][Oo]) - user_canceled - ;; - *) - input_error - ;; - esac - fi - fi -} - +# Configure bastille loopback network interface configure_network() { - local _response + info "Configuring ${bastille_network_loopback} loopback interface" + sysrc cloned_interfaces+=lo1 + sysrc ifconfig_lo1_name="${bastille_network_loopback}" - # Configure bastille loopback network interface. - # This is an initial attempt to make this function interactive, - # however this may be enhanced in the future by advanced contributors in this topic. - info "This will attempt to configure the loopback network interface [${bastille_network_loopback}]." - warn "Would you like to configure the loopback network interface now? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - # shellcheck disable=SC2104 - break - ;; - [Nn]|[Nn][Oo]) - user_canceled - ;; - *) - input_error - ;; - esac - - info "Configuring ${bastille_network_loopback} loopback interface..." - if ! sysrc -qn cloned_interfaces | grep -qi "lo1"; then - sysrc cloned_interfaces+="lo1" - fi - if ! sysrc -qn ifconfig_lo1_name | grep -qi "${bastille_network_loopback}"; then - sysrc ifconfig_lo1_name="${bastille_network_loopback}" - fi - - info "Bringing up new interface: ${bastille_network_loopback}..." + info "Bringing up new interface: ${bastille_network_loopback}" service netif cloneup } configure_vnet() { - local _response + info "Configuring bridge interface" + sysrc cloned_interfaces+=bridge1 + sysrc ifconfig_bridge1_name=bastille1 - # This is an initial attempt to make this function interactive, - # however this may be enhanced in the future by advanced contributors in this topic. - info "This will attempt to configure the VNET bridge interface [${bastille_ifbridge_name}]." - warn "Would you like to configure the VNET bridge interface now? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - # shellcheck disable=SC2104 - break - ;; - [Nn]|[Nn][Oo]) - user_canceled - ;; - *) - input_error - ;; - esac - - info "Configuring bridge interface [${bastille_ifbridge_name}]..." - - if ! sysrc -qn cloned_interfaces | grep -qi "${bastille_ifbridge_name}"; then - sysrc cloned_interfaces+="${bastille_ifbridge_name}" - fi - if ! sysrc -qn ifconfig_bridge1_name | grep -qi "${bastille_ifbridge_name}"; then - sysrc ifconfig_bridge1_name="${bastille_ifbridge_name}" - fi - - info "Bringing up new interface: ${bastille_ifbridge_name}..." + info "Bringing up new interface: bastille1" service netif cloneup - if [ ! -f "/etc/devfs.rules" ]; then - info "Creating bastille_vnet devfs.rules..." + if [ ! -f /etc/devfs.rules ]; then + info "Creating bastille_vnet devfs.rules" cat << EOF > /etc/devfs.rules -# Auto-generated file from `bastille setup` -# devfs configuration information - [bastille_vnet=13] add include \$devfsrules_hide_all add include \$devfsrules_unhide_basic @@ -518,48 +73,22 @@ add include \$devfsrules_jail add include \$devfsrules_jail_vnet add path 'bpf*' unhide EOF - else - warn "File [/etc/devfs.rules] already exist, skipping." - exit 1 fi - exit 0 } +# Configure pf firewall configure_pf() { - local _response - - # Configure the PF firewall. - # This is an initial attempt to make this function interactive, - # however this may be enhanced in the future by advanced contributors in this topic. - info "This will attempt to configure the PF firewall parameters in [${bastille_pf_conf}]." - warn "Would you like to configure the PF firewall parameters now? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - # shellcheck disable=SC2104 - break - ;; - [Nn]|[Nn][Oo]) - user_canceled - ;; - *) - input_error - ;; - esac - - # shellcheck disable=SC2154 - if [ ! -f "${bastille_pf_conf}" ]; then - # shellcheck disable=SC3043 - local ext_if - ext_if=$(netstat -rn | awk '/default/ {print $4}' | head -n1) - info "Determined default network interface: ($ext_if)" - info "${bastille_pf_conf} does not exist: creating..." - - # Creating pf.conf file. - cat << EOF > "${bastille_pf_conf}" -# Auto-generated file from `bastille setup` -# packet filter configuration file +# shellcheck disable=SC2154 +if [ ! -f "${bastille_pf_conf}" ]; then + # shellcheck disable=SC3043 + local ext_if + ext_if=$(netstat -rn | awk '/default/ {print $4}' | head -n1) + info "Determined default network interface: ($ext_if)" + info "${bastille_pf_conf} does not exist: creating..." + ## creating pf.conf + cat << EOF > "${bastille_pf_conf}" +## generated by bastille setup ext_if="$ext_if" set block-policy return @@ -575,417 +104,58 @@ pass out quick keep state antispoof for \$ext_if inet pass in inet proto tcp from any to any port ssh flags S/SA keep state EOF - - if ! sysrc -qn pf_enable | grep -qi "yes"; then - sysrc pf_enable="YES" - fi - warn "The pf ruleset file has been created, please review '${bastille_pf_conf}' and enable it using 'service pf start'." - else - warn "${bastille_pf_conf} already exists, skipping." - exit 1 - fi - exit 0 + sysrc pf_enable=YES + warn "pf ruleset created, please review ${bastille_pf_conf} and enable it using 'service pf start'." +else + error_exit "${bastille_pf_conf} already exists. Exiting." +fi } +# Configure ZFS configure_zfs() { - # Attempt to detect and setup either new or an existing bastille ZFS on-disk configuration. - # This is useful for new users to easily activate the bastille ZFS parameters on a standard installation, - # or to recover an existing on-disk ZFS bastille configuration in case the config file has been borked/reset by the user, - # also a config backup will be created each time the config needs to be modified in the following format: bastille.conf.YYYYMMDD-HHMMSS - # Be aware that the users now need to explicitly enable ZFS in the config file due later config file changes, failing to do so - # before initial `bastille bootstrap` will private the user from activating ZFS storage features without manual intervention. - - ZFS_DATASET_DETECT= - BASTILLE_CUSTOM_CONFIG= - local _response= - - if ! kldstat -qm zfs; then - warn "Looks like the ZFS module is not loaded." - warn "If this is not a dedicated ZFS system you can ignore this warning." - exit 1 + if [ ! "$(kldstat -m zfs)" ]; then + info "ZFS module not loaded; skipping..." else - # If the below statement becomes true, will assume that the user do not want ZFS activation at all regardless of the - # host filesystem, or the default configuration file has been changed officially and set to "NO" by default. - if echo "${bastille_zfs_enable}" | grep -qi "no"; then - info "Looks like Bastille ZFS has been disabled in 'bastille.conf', ZFS activation helper disabled." - warn "Would you like to enable the ZFS activation helper now? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - # Assume the user wants to configure the ZFS parameters. - if config_backup; then - write_zfs_enable - warn "Please run 'bastille setup' again or consult bastille.conf for further configuration." - exit 0 - else - error_exit "Config backup creation failed, exiting." - fi - ;; - [Nn]|[Nn][Oo]) - # Assume the user will manually configure the ZFS parameters, or skip ZFS configuration. - user_canceled - ;; - esac - else - # Attempt to detect if bastille was installed with sane defaults(ports/pkg) and hasn't been bootstrapped yet, - # then offer the user initial ZFS activation option to gain all of the ZFS storage features and benefits. - # This should be performed before `bastille` initial bootstrap because several ZFS datasets will be - # created/configured during the bootstrap process by default. - get_zfs_params - if [ ! -d "${bastille_prefix}" ] && [ -n "${BASTILLE_ZFSPOOL}" ]; then - if [ "${bastille_prefix}" = "${bastille_prefix_default}" ] && [ -z "${BASTILLE_CUSTOM_CONFIG}" ]; then - show_zfs_params - info "Looks like bastille has been installed and hasn't been bootstrapped yet." - warn "Would you like to activate ZFS now to get the features and benefits? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - if [ -n "${BASTILLE_ZFSPOOL}" ]; then - info "Attempting to create a backup file of the current bastille.conf file..." - if config_backup; then - write_zfs_opts - create_zfs_dataset - else - error_exit "Config backup creation failed, exiting." - fi - else - error_exit "Unable to determine the [zroot] pool name, exiting" - fi - ;; - [Nn]|[Nn][Oo]) - info "Looks like you cancelled the ZFS activation." - # Offer the user option to disable ZFS in the configuration file. - # Maybe the user wants to use UFS or ZFS with legacy directories instead. - warn "Would you like to explicitly disable ZFS in the configuration file? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - if config_backup; then - # Assume the user want to skip ZFS configuration regardless. - write_zfs_disable - exit 0 - else - error_exit "Config backup creation failed, exiting." - fi - ;; - [Nn]|[Nn][Oo]) - # Assume the user will manually configure the ZFS parameters by itself. - user_canceled - ;; - *) - input_error - ;; - esac - ;; - *) - input_error - ;; - esac - else - config_validation - fi - else - if [ -d "${bastille_prefix}" ] && [ -z "${bastille_zfs_enable}" ] && [ -z "${bastille_zfs_zpool}" ] && [ -z "${BASTILLE_CUSTOM_CONFIG}" ] && [ -z "${BASTILLE_UFSBOOT}" ]; then - show_zfs_params - # This section is handy if the user has reset the bastille configuration file after a successful ZFS activation. - info "Looks like bastille has been bootstrapped already, but ZFS options are not configured." - info "Attempting to configure default ZFS options for you..." - if zfs list | grep -qw "${bastille_prefix}"; then - ZFS_DATASET_DETECT="1" - warn "Would you like to auto-configure the detected ZFS parameters now? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - if config_backup; then - write_zfs_opts - exit 0 - else - error_exit "Config backup creation failed, exiting." - fi - ;; - [Nn]|[Nn][Oo]) - # Assume the user will manually configure the ZFS parameters by itself. - user_canceled - ;; - *) - input_error - ;; - esac - else - if [ -d "${bastille_prefix}" ]; then - if [ ! "$(ls -A ${bastille_prefix})" ]; then - if ! zfs list | grep -qw "${bastille_prefix}"; then - # If the user want to use ZFS he/she need to remove/rename the existing 'bastille_prefix' directory manually. - # We do not want to cause existing data lost at all due end-user errors. - warn "Looks like bastille prefix is not a ZFS dataset, thus ZFS storage options are not required." - warn "Please refer to 'bastille.conf' and/or verify for alreay existing 'bastille_prefix' directory." - warn "Would you like to explicitly disable ZFS in the configuration file so we don't ask again? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - if config_backup; then - write_zfs_disable - exit 0 - else - error_exit "Config backup creation failed, exiting." - fi - ;; - [Nn]|[Nn][Oo]) - # Assume the user will manually configure the ZFS parameters by itself. - user_canceled - ;; - *) - input_error - ;; - esac - fi - else - error_exit "Looks like 'bastille_prefix' is not a ZFS dataset and is not empty, aborting." - fi - fi - fi - fi - if [ -n "${BASTILLE_CUSTOM_CONFIG}" ]; then - # Attempt to detect an existing on-disk bastille ZFS configuration and let the user interactively select the items manually from a list. - # This should be performed if the user has borked/reset the config file or in the event the setup detected an unusual/customized bastille install. - warn "A custom bastille ZFS configuration has been detected and/or unable to read ZFS configuration properly." - warn "Please refer to 'bastille.conf' config file and/or 'bastille setup -help' for additional info." - zfs_initial_activation - else - config_validation - fi - fi + ## attempt to determine bastille_zroot from `zpool list` + bastille_zroot=$(zpool list | grep -v NAME | awk '{print $1}') + if [ "$(echo "${bastille_zroot}" | wc -l)" -gt 1 ]; then + error_notify "Error: Multiple ZFS pools available:\n${bastille_zroot}" + error_notify "Set desired pool using \"sysrc -f ${bastille_config} bastille_zfs_zpool=ZPOOL_NAME\"" + error_exit "Don't forget to also enable ZFS using \"sysrc -f ${bastille_config} bastille_zfs_enable=YES\"" fi + sysrc -f "${bastille_config}" bastille_zfs_enable=YES + sysrc -f "${bastille_config}" bastille_zfs_zpool="${bastille_zroot}" fi } -configure_zfs_manually() { - BASTILLE_CONFIG_USER= - local ZFSPOOL_COUNT="0" - local ZFSDATA_COUNT="0" - local MPREFIX_COUNT="0" - local _zfsprefix_trim= - local _zfspool_choice= - local _zfspool_select= - local _zfsprefix_choice= - local _zfsprefix_select= - local _zfsmount_choice= - local _zfsmount_select= - local _response= +# Run all base functions (w/o vnet) if no args +if [ $# -eq 0 ]; then + sysrc bastille_enable=YES + configure_network + configure_pf + configure_zfs +fi - info "Would you like to configure the ZFS parameters entirely by hand? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - # We will assume the user knows what hes/she doing and want to configure ZFS parameters entirely by hand. - warn "Please enter the desired ZFS pool for bastille: " - read _zfspool_select - warn "Please enter the ZFS dataset for bastille: " - read _zfsprefix_select - warn "Please enter the ZFS mountpoint for bastille: " - read _zfsmount_select - - # Set the parameters and show the user a preview. - BASTILLE_PREFIXDEF="${_zfsmount_select}" - BASTILLE_ZFSPOOL="${_zfspool_select}" - BASTILLE_PREFIXZFS="${_zfsprefix_select}" - show_zfs_params - - # Ask again to make sure the user is confident with the entered parameters. - warn "Are you sure the above bastille ZFS configuration is correct?" - warn "Once bastille is activated it can't be easily undone, do you really want to activate ZFS now? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - BASTILLE_CONFIG_USER="1" - write_zfs_opts - create_zfs_dataset - ;; - [Nn]|[Nn][Oo]) - user_canceled - ;; - *) - input_error - ;; - esac - ;; - [Nn]|[Nn][Oo]) - # shellcheck disable=SC2104 - break - ;; - *) - input_error - ;; - esac - - # Ask here several times as we want the user to be really sure of what they doing, - # We do not want to cause existing data lost at all due end-user errors. - info "Listing available ZFS pools..." - bastille_zpool=$(zpool list -H | awk '{print $1}') - for _zpool in ${bastille_zpool}; do - echo "[${ZFSPOOL_COUNT}] ${_zpool}" - ZFSPOOL_NUM="${ZFSPOOL_NUM} [${ZFSPOOL_COUNT}]${_zpool}" - ZFSPOOL_COUNT=$(expr ${ZFSPOOL_COUNT} + 1) - done - - info "Please select the ZFS pool [NUM] for bastille: " - read _zfspool_choice - if ! echo "${_zfspool_choice}" | grep -Eq "^[0-9]{1,3}$"; then - error_exit "Invalid input number, aborting!" - else - _zfspool_select=$(echo "${ZFSPOOL_NUM}" | grep -wo "\[${_zfspool_choice}\][^ ]*" | sed 's/\[.*\]//g') - # If the user is unsure here, just abort as no input validation will be performed after. - if [ -z "${_zfspool_select}" ]; then - error_exit "No ZFS pool selected, aborting!" - else - info "Selected ZFS pool: [${_zfspool_select}]" - # Ask again to make sure the user is confident with the election. - warn "Are you sure '${_zfspool_select}' is the correct ZFS pool [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - # shellcheck disable=SC2104 - continue - ;; - [Nn]|[Nn][Oo]) - user_canceled - ;; - *) - input_error - ;; - esac - fi - fi - - # Ask on what zfs dataset `bastille` is installed. - info "Listing available ZFS datasets from the selected ZFS pool..." - bastille_zprefix=$(zfs list -H -r "${_zfspool_select}" | awk '{print $1}') - for _zprefix in ${bastille_zprefix}; do - echo "[${ZFSDATA_COUNT}] ${_zprefix}" - ZFSDATA_NUM="${ZFSDATA_NUM} [${ZFSDATA_COUNT}]${_zprefix}" - ZFSDATA_COUNT=$(expr ${ZFSDATA_COUNT} + 1) - done - info "Please select the ZFS dataset [NUM] for bastille: " - read _zfsprefix_choice - if ! echo "${_zfsprefix_choice}" | grep -Eq "^[0-9]{1,3}$"; then - error_exit "Invalid input number, aborting!" - else - _zfsprefix_select=$(echo "${ZFSDATA_NUM}" | grep -wo "\[${_zfsprefix_choice}\][^ ]*" | sed 's/\[.*\]//g') - if [ -z "${_zfsprefix_select}" ]; then - # If the user is unsure here, just abort as no input validation will be performed after. - error_exit "No ZFS dataset selected, aborting!" - else - _zfsprefix_select=$(echo ${ZFSDATA_NUM} | grep -wo "\[${_zfsprefix_choice}\][^ ]*" | sed 's/\[.*\]//g') - _zfsprefix_trim=$(echo ${ZFSDATA_NUM} | grep -wo "\[${_zfsprefix_choice}\][^ ]*" | awk -F "${_zfspool_select}/" 'NR==1{print $2}') - info "Selected ZFS prefix: [${_zfsprefix_select}]" - # Ask again to make sure the user is confident with the election. - warn "Are you sure '${_zfsprefix_select}' is the correct ZFS dataset [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - # shellcheck disable=SC2104 - continue - ;; - [Nn]|[Nn][Oo]) - user_canceled - ;; - *) - input_error - ;; - esac - fi - fi - - _zfsmount_select="${_zfsprefix_select}" - # Ask what zfs mountpoint `bastille` will use. - info "Listing ZFS mountpoints from the selected ZFS dataset: [${_zfsmount_select}]..." - bastille_prefix=$(zfs list -H "${_zfsmount_select}" | awk '{print $5}') - for _zfsmount_choice in ${bastille_prefix}; do - echo "[${MPREFIX_COUNT}] ${_zfsmount_choice}" - MPREFIX_NUM="${MPREFIX_NUM} [${MPREFIX_COUNT}]${_zfsmount_choice}" - MPREFIX_COUNT=$(expr ${MPREFIX_COUNT} + 1) - done - info "Please select the ZFS mountpoint [NUM] for bastille: " - read _zfsmount_choice - if ! echo "${_zfsmount_choice}" | grep -Eq "^[0-9]{1,3}$"; then - error_exit "Invalid input number, aborting!" - else - _zfsmount_select=$(echo ${MPREFIX_NUM} | grep -wo "\[${_zfsmount_choice}\][^ ]*" | sed 's/\[.*\]//g') - if [ -z "${_zfsmount_select}" ]; then - # If the user is unsure here, just abort as no input validation will be performed after. - error_exit "No ZFS mountpoint selected, aborting!" - else - info "Selected bastille storage mountpoint: [${_zfsmount_select}]" - # Ask again to make sure the user is confident with the election. - warn "Are you sure '${_zfsmount_select}' is the correct bastille prefix [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - # Set the parameters and show the user a preview. - BASTILLE_PREFIXDEF="${_zfsmount_select}" - BASTILLE_ZFSPOOL="${_zfspool_select}" - BASTILLE_PREFIXZFS="${_zfsprefix_trim}" - show_zfs_params - warn "Are you sure the above bastille ZFS configuration is correct?" - warn "Once bastille is activated it can't be easily undone, do you really want to activate ZFS now? [y/N]: " - read _response - case "${_response}" in - [Yy]|[Yy][Ee][Ss]) - write_zfs_opts - create_zfs_dataset - ;; - [Nn]|[Nn][Oo]) - user_canceled - ;; - *) - input_error - ;; - esac - ;; - [Nn]|[Nn][Oo]) - user_canceled - ;; - *) - input_error - ;; - esac - fi - fi -} - -# Runtime required variables. -config_runtime - -# Handle options one at a time per topic, we don't want users to select/process -# multiple options at once just to end with a broked and/or unwanted configuration. -case "${1}" in - --firewall|-p) - configure_pf - ;; - --ethernet|-e) - configure_ethernet - ;; - --network|-n|bastille0) - # TODO remove in future release 0.13 - warn "Notice: 'bastille setup bastille0' will be deprecated in the next 0.13 version." - configure_network - ;; - --vnet|-v|bridge) - configure_vnet - ;; - --zfs|-z) - configure_zfs - ;; - --conf-network-reset) - config_network_reset - ;; - --conf-storage-reset) - config_storage_reset - ;; - --conf-restore-clean) - config_restore_global - ;; - *) - usage - ;; +# Handle special-case commands first. +case "$1" in +help|-h|--help) + usage + ;; +pf|firewall) + configure_pf + ;; +bastille0) + # TODO remove in future release 0.13 + warn "'bastille setup bastille0' will be deprecated in the next 0.13 version." + configure_network + ;; +network|loopback) + configure_network + ;; +zfs|storage) + configure_zfs + ;; +bastille1|vnet|bridge) + configure_vnet + ;; esac From 43e186899dbfd3d6f30d06dbaa4d697898bec9eb Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Sun, 26 Jan 2025 19:40:07 -0700 Subject: [PATCH 137/141] README: Fix reference to rcp --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1dcc5c7c..4ce958c3 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Available Commands: list List containers (running). mount Mount a volume inside the targeted container(s). pkg Manipulate binary packages within targeted container(s). See pkg(8). + rcp cp(1) files from a jail to host. rdr Redirect host port to container port. rename Rename a container. restart Restart a running container. From 6d033ab227bcab1a97d31bfe94169765dd5259d4 Mon Sep 17 00:00:00 2001 From: Juan David Hurtado G Date: Sun, 26 Jan 2025 21:56:26 -0500 Subject: [PATCH 138/141] readme: Adds jcp subcommand information --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4ce958c3..6605202f 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ Available Commands: help Help about any command. htop Interactive process viewer (requires htop). import Import a specified container. + jcp cp(1) files from a jail to jail(s). limits Apply resources limits to targeted container(s). See rctl(8). list List containers (running). mount Mount a volume inside the targeted container(s). From c21a2386071e55b6d486a261be9dad2920d926af Mon Sep 17 00:00:00 2001 From: Juan David Hurtado G Date: Sun, 26 Jan 2025 22:13:10 -0500 Subject: [PATCH 139/141] authors: Add Victor Tschetter --- AUTHORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.md b/AUTHORS.md index 3a777ac1..353f1961 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -28,6 +28,7 @@ Christer Edwards [christer.edwards@gmail.com] - Niketh Murali - Eric Borisch - Kevet Duncombe +- Victor Tschetter ### Special thanks Software doesn't happen in a vacuum. Thank you to the following people who may From 00f09ef7385d1c5c1ab0a010fe764b8eb1e0cef8 Mon Sep 17 00:00:00 2001 From: Juan David Hurtado G Date: Sun, 26 Jan 2025 22:15:08 -0500 Subject: [PATCH 140/141] version 0.13.20250126 --- README.md | 2 +- docs/chapters/installation.rst | 2 +- docs/conf.py | 4 ++-- usr/local/bin/bastille | 2 +- usr/local/share/bastille/etcupdate.sh | 2 +- usr/local/share/bastille/rename.sh | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6605202f..ca2d2d38 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ Use "bastille command -h|--help" for more information about a command. ``` -## 0.12-beta +## 0.13-beta This document outlines the basic usage of the Bastille container management framework. This release is still considered beta. diff --git a/docs/chapters/installation.rst b/docs/chapters/installation.rst index 232988c9..1596813b 100644 --- a/docs/chapters/installation.rst +++ b/docs/chapters/installation.rst @@ -4,7 +4,7 @@ Bastille is available in the official FreeBSD ports tree at `sysutils/bastille`. Binary packages available in `quarterly` and `latest` repositories. -Current version is `0.12.20250111`. +Current version is `0.13.20250126`. To install from the FreeBSD package repository: diff --git a/docs/conf.py b/docs/conf.py index 96451510..c2f36b89 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,9 +12,9 @@ copyright = '2018-2025, Christer Edwards' author = 'Christer Edwards' # The short X.Y version -version = '0.12.20250111' +version = '0.13.20250126' # The full version, including alpha/beta/rc tags -release = '0.12.20250111-beta' +release = '0.13.20250126-beta' # -- General configuration --------------------------------------------------- diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index d89baf15..d8439beb 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -78,7 +78,7 @@ bastille_perms_check() { bastille_perms_check ## version -BASTILLE_VERSION="0.12.20250111" +BASTILLE_VERSION="0.13.20250126" usage() { cat << EOF diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index 9e4f6c68..1f0979be 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (c) 2018-2024, Christer Edwards +# Copyright (c) 2018-2025, Christer Edwards # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/usr/local/share/bastille/rename.sh b/usr/local/share/bastille/rename.sh index 52e206f7..7aa887b8 100644 --- a/usr/local/share/bastille/rename.sh +++ b/usr/local/share/bastille/rename.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2018-2024, Christer Edwards +# Copyright (c) 2018-2025, Christer Edwards # All rights reserved. # # Redistribution and use in source and binary forms, with or without From 205be1afdd703a51e5b9fc6109e4e656112b605f Mon Sep 17 00:00:00 2001 From: tschettervictor <85497460+tschettervictor@users.noreply.github.com> Date: Wed, 29 Jan 2025 07:59:47 -0700 Subject: [PATCH 141/141] console: Fix _jail > TARGET --- usr/local/share/bastille/console.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr/local/share/bastille/console.sh b/usr/local/share/bastille/console.sh index 96690b3d..33851a05 100644 --- a/usr/local/share/bastille/console.sh +++ b/usr/local/share/bastille/console.sh @@ -94,10 +94,10 @@ fi validate_user() { if jexec -l "${TARGET}" id "${USER}" >/dev/null 2>&1; then - USER_SHELL="$(jexec -l "${_jail}" getent passwd "${USER}" | cut -d: -f7)" + USER_SHELL="$(jexec -l "${TARGET}" getent passwd "${USER}" | cut -d: -f7)" if [ -n "${USER_SHELL}" ]; then - if jexec -l "${_jail}" grep -qwF "${USER_SHELL}" /etc/shells; then - jexec -l "${_jail}" $LOGIN -f "${USER}" + if jexec -l "${TARGET}" grep -qwF "${USER_SHELL}" /etc/shells; then + jexec -l "${TARGET}" $LOGIN -f "${USER}" else echo "Invalid shell for user ${USER}" fi