diff --git a/usr/local/share/bastille/bootstrap.sh b/usr/local/share/bastille/bootstrap.sh index ab33c376..8556421a 100644 --- a/usr/local/share/bastille/bootstrap.sh +++ b/usr/local/share/bastille/bootstrap.sh @@ -45,13 +45,19 @@ EOF } validate_release_url() { + + info "\nBootstrapping release: ${RELEASE}..." + ## check upstream url, else warn user if [ -n "${NAME_VERIFY}" ]; then + RELEASE="${NAME_VERIFY}" + + info "\nFetching ${PLATFORM_OS} distfiles..." + if ! fetch -qo /dev/null "${UPSTREAM_URL}/MANIFEST" 2>/dev/null; then error_exit "Unable to fetch MANIFEST. See 'bootstrap urls'." fi - info "Bootstrapping ${PLATFORM_OS} distfiles..." # Alternate RELEASE/ARCH fetch support if [ "${OPTION}" = "--i386" ] || [ "${OPTION}" = "--32bit" ]; then @@ -61,13 +67,15 @@ validate_release_url() { bootstrap_directories bootstrap_release + else usage fi } bootstrap_directories() { - ## ensure required directories are in place + + # Ensure required directories are in place ## ${bastille_prefix} if [ ! -d "${bastille_prefix}" ]; then @@ -81,7 +89,7 @@ bootstrap_directories() { chmod 0750 "${bastille_prefix}" # Make sure the dataset is mounted in the proper place elif [ -d "${bastille_prefix}" ]; then - if ! zfs list "${bastille_zfs_zpool}/${bastille_zfs_prefix}" 2>/dev/null; then + if ! zfs list "${bastille_zfs_zpool}/${bastille_zfs_prefix}" >/dev/null; then zfs create ${bastille_zfs_options} -o mountpoint="${bastille_prefix}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}" elif [ "$(zfs get -H -o value mountpoint ${bastille_zfs_zpool}/${bastille_zfs_prefix})" != "${bastille_prefix}" ]; then zfs set mountpoint="${bastille_prefix}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}" @@ -188,6 +196,7 @@ bootstrap_directories() { } bootstrap_release() { + ## if release exists quit, else bootstrap additional distfiles if [ -f "${bastille_releasesdir}/${RELEASE}/COPYRIGHT" ]; then ## check distfiles list and skip existing cached files @@ -201,9 +210,9 @@ bootstrap_release() { ## check if release already bootstrapped, else continue bootstrapping if [ -z "${bastille_bootstrap_archives}" ]; then - error_notify "Bootstrap appears complete." + error_exit "Bootstrap appears complete." else - info "Bootstrapping additional distfiles..." + info "\nFetching additional distfiles..." fi fi @@ -211,13 +220,13 @@ bootstrap_release() { ## check if the dist files already exists then extract FETCH_VALIDATION="0" if [ -f "${bastille_cachedir}/${RELEASE}/${_archive}.txz" ]; then - info "Extracting ${PLATFORM_OS} ${RELEASE} ${_archive}.txz." + info "Extracting ${PLATFORM_OS} ${RELEASE} ${_archive}.txz..." if /usr/bin/tar -C "${bastille_releasesdir}/${RELEASE}" -xf "${bastille_cachedir}/${RELEASE}/${_archive}.txz"; then ## silence motd at container login touch "${bastille_releasesdir}/${RELEASE}/root/.hushlogin" touch "${bastille_releasesdir}/${RELEASE}/usr/share/skel/dot.hushlogin" else - error_exit "Failed to extract ${_archive}.txz." + error_exit "[ERROR]: Failed to extract ${_archive}.txz." fi else ## get the manifest for dist files checksum validation @@ -247,14 +256,14 @@ bootstrap_release() { rm -rf "${bastille_releasesdir:?}/${RELEASE}" fi fi - error_exit "Bootstrap failed." + error_exit "[ERROR]: Bootstrap failed." fi ## fetch for missing dist files if [ ! -f "${bastille_cachedir}/${RELEASE}/${_archive}.txz" ]; then if ! fetch "${UPSTREAM_URL}/${_archive}.txz" -o "${bastille_cachedir}/${RELEASE}/${_archive}.txz"; then ## alert only if unable to fetch additional dist files - error_notify "Failed to fetch ${_archive}.txz." + error_exit "[ERROR]: Failed to fetch ${_archive}.txz" fi fi @@ -264,31 +273,30 @@ bootstrap_release() { SHA256_FILE=$(sha256 -q "${bastille_cachedir}/${RELEASE}/${_archive}.txz") if [ "${SHA256_FILE}" != "${SHA256_DIST}" ]; then rm "${bastille_cachedir}/${RELEASE}/${_archive}.txz" - error_exit "Failed validation for ${_archive}.txz. Please retry bootstrap!" + error_exit "[ERROR]: Failed validation for ${_archive}.txz. Please retry bootstrap!" else - info "Validated checksum for ${RELEASE}: ${_archive}.txz" - info "MANIFEST: ${SHA256_DIST}" - info "DOWNLOAD: ${SHA256_FILE}" + info "\nValidated checksum for ${RELEASE}: ${_archive}.txz" + echo "MANIFEST: ${SHA256_DIST}" + echo "DOWNLOAD: ${SHA256_FILE}" fi fi ## extract the fetched dist files if [ -f "${bastille_cachedir}/${RELEASE}/${_archive}.txz" ]; then - info "Extracting ${PLATFORM_OS} ${RELEASE} ${_archive}.txz." + info "\nExtracting ${PLATFORM_OS} ${RELEASE} ${_archive}.txz..." if /usr/bin/tar -C "${bastille_releasesdir}/${RELEASE}" -xf "${bastille_cachedir}/${RELEASE}/${_archive}.txz"; then ## silence motd at container login touch "${bastille_releasesdir}/${RELEASE}/root/.hushlogin" touch "${bastille_releasesdir}/${RELEASE}/usr/share/skel/dot.hushlogin" else - error_exit "Failed to extract ${_archive}.txz." + error_exit "[ERROR]: Failed to extract ${_archive}.txz." fi fi fi done - echo - info "Bootstrap successful." - info "See 'bastille --help' for available commands." + info "\nBootstrap successful." + echo "See 'bastille --help' for available commands." } @@ -311,22 +319,22 @@ debootstrap_release() { read answer case "${answer}" in [Nn][Oo]|[Nn]|"") - error_exit "Exiting." + error_exit "Cancelled, Exiting." ;; [Yy][Ee][Ss]|[Yy]) # Skip already loaded known modules. if ! kldstat -m ${_req_kmod} >/dev/null 2>&1; then - info "Loading kernel module: ${_req_kmod}" + info "\nLoading kernel module: ${_req_kmod}" kldload -v ${_req_kmod} fi - info "Persisting module: ${_req_kmod}" + info "\nPersisting module: ${_req_kmod}" sysrc -f /boot/loader.conf ${_req_kmod}_load=YES ;; esac else # If already set in /boot/loader.conf, check and try to load the module. if ! kldstat -m ${_req_kmod} >/dev/null 2>&1; then - info "Loading kernel module: ${_req_kmod}" + info "\nLoading kernel module: ${_req_kmod}" kldload -v ${_req_kmod} fi fi @@ -335,10 +343,11 @@ debootstrap_release() { # Mandatory Linux modules/rc. for _lin_kmod in ${linuxarc_mods}; do if ! kldstat -n ${_lin_kmod} >/dev/null 2>&1; then - info "Loading kernel module: ${_lin_kmod}" + info "\nLoading kernel module: ${_lin_kmod}" kldload -v ${_lin_kmod} fi done + if [ ! "$(sysrc -qn linux_enable)" = "YES" ] && \ [ ! "$(sysrc -f /etc/rc.conf.local -qn linux_enable)" = "YES" ]; then sysrc linux_enable=YES @@ -349,7 +358,7 @@ debootstrap_release() { read answer case $answer in [Nn][Oo]|[Nn]|"") - error_exit "Exiting. You need to install debootstap before boostrapping a Linux jail." + error_exit "[ERROR]: debootstrap is required for boostrapping a Linux jail." ;; [Yy][Ee][Ss]|[Yy]) pkg install -y debootstrap @@ -358,8 +367,9 @@ debootstrap_release() { fi # Fetch the Linux flavor - info "Bootstrapping ${PLATFORM_OS} distfiles..." + info "\nFetching ${PLATFORM_OS} distfiles..." if ! debootstrap --foreign --arch=${ARCH_BOOTSTRAP} --no-check-gpg ${LINUX_FLAVOR} "${bastille_releasesdir}"/${DIR_BOOTSTRAP}; then + ## perform cleanup only for stale/empty directories on failure if checkyesno bastille_zfs_enable; then if [ -n "${bastille_zfs_zpool}" ]; then @@ -368,12 +378,13 @@ debootstrap_release() { fi fi fi + if [ -d "${bastille_releasesdir}/${DIR_BOOTSTRAP}" ]; then if [ ! "$(ls -A "${bastille_releasesdir}/${DIR_BOOTSTRAP}")" ]; then rm -rf "${bastille_releasesdir:?}/${DIR_BOOTSTRAP}" fi fi - error_exit "Bootstrap failed." + error_exit "[ERROR]: Bootstrap failed." fi case "${LINUX_FLAVOR}" in @@ -383,8 +394,8 @@ debootstrap_release() { ;; esac - info "Bootstrap successful." - info "See 'bastille --help' for available commands." + info "\nBootstrap successful." + info "\nSee 'bastille --help' for available commands." } bootstrap_template() { @@ -455,7 +466,7 @@ while [ "$#" -gt 0 ]; do shift ;; -*) - error_exit "Unknown Option: \"${1}\"" + error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; *) break @@ -477,27 +488,27 @@ if [ "$(sysrc -n zfs_enable)" = "YES" ] && ! checkyesno bastille_zfs_enable; the read answer case $answer in no|No|n|N|"") - error_exit "ERROR: Missing ZFS parameters. See bastille_zfs_enable." + error_exit "[ERROR]: Missing ZFS parameters. See bastille_zfs_enable." ;; yes|Yes|y|Y) ;; esac fi -# Validate ZFS parameters. +# Validate ZFS parameters if checkyesno bastille_zfs_enable; then ## check for the ZFS pool and bastille prefix if [ -z "${bastille_zfs_zpool}" ]; then - error_exit "ERROR: Missing ZFS parameters. See bastille_zfs_zpool." + error_exit "[ERROR]: Missing ZFS parameters. See bastille_zfs_zpool." elif [ -z "${bastille_zfs_prefix}" ]; then - error_exit "ERROR: Missing ZFS parameters. See bastille_zfs_prefix." + error_exit "[ERROR]: Missing ZFS parameters. See bastille_zfs_prefix." elif ! zfs list "${bastille_zfs_zpool}" > /dev/null 2>&1; then - error_exit "ERROR: ${bastille_zfs_zpool} is not a ZFS pool." + error_exit "[ERROR]: ${bastille_zfs_zpool} is not a ZFS pool." fi ## check for the ZFS dataset prefix if already exist if [ -d "/${bastille_zfs_zpool}/${bastille_zfs_prefix}" ]; then if ! zfs list "${bastille_zfs_zpool}/${bastille_zfs_prefix}" > /dev/null 2>&1; then - error_exit "ERROR: ${bastille_zfs_zpool}/${bastille_zfs_prefix} is not a ZFS dataset." + error_exit "[ERROR]: ${bastille_zfs_zpool}/${bastille_zfs_prefix} is not a ZFS dataset." fi fi fi @@ -517,7 +528,7 @@ if [ -n "${OPTION}" ] && [ "${OPTION}" != "${HW_MACHINE}" ] && [ "${OPTION}" != HW_MACHINE="i386" HW_MACHINE_ARCH="i386" else - error_exit "Unsupported architecture." + error_exit "[ERROR]: Unsupported architecture." fi fi diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index 50abbefa..39b52733 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -76,7 +76,7 @@ while [ "$#" -gt 0 ]; do a) AUTO=1 ;; l) LIVE=1 ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" esac done shift @@ -104,18 +104,26 @@ 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(.)!" + error_exit "[ERROR]: Jail names may not contain a dot(.)!" fi validate_ip() { + + local IP="${1}" IP6_MODE="disable" ip6=$(echo "${IP}" | grep -E '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$))') + if [ -n "${ip6}" ]; then - info "Valid: (${ip6})." + + info "\nValid: (${ip6})." IP6_MODE="new" + elif { [ "${IP}" = "0.0.0.0" ] || [ "${IP}" = "DHCP" ]; } && [ "$(bastille config ${TARGET} get vnet)" = "enabled" ]; then - info "Valid: (${IP})." + + info "\nValid: (${IP})." + else + local IFS if echo "${IP}" | grep -Eq '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))?$'; then TEST_IP=$(echo "${IP}" | cut -d / -f1) @@ -126,11 +134,13 @@ validate_ip() { error_exit "Invalid: (${TEST_IP})" fi done + if ifconfig | grep -qwF "${TEST_IP}"; then - warn "Warning: IP address already in use (${TEST_IP})." + warn "\nWarning: IP address already in use (${TEST_IP})." else - info "Valid: (${IP})." + info "\nValid: (${IP})." fi + else error_exit "Invalid: (${IP})." fi @@ -138,8 +148,10 @@ validate_ip() { } 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}" @@ -161,6 +173,7 @@ update_jailconf() { if [ "${_interface}" != "not set" ]; then sed -i '' "/.*interface = .*/d" "${JAIL_CONFIG}" fi + # IP4 if [ "${_ip4}" != "not set" ]; then for _ip in ${_ip4}; do @@ -175,6 +188,7 @@ update_jailconf() { sed -i '' "/ip4.addr += .*/ s/${_ip}/127.0.0.1/" "${JAIL_CONFIG}" done fi + # IP6 if [ "${_ip6}" != "not set" ]; then for _ip in ${_ip6}; do @@ -216,6 +230,7 @@ update_jailconf_vnet() { if echo ${_if} | grep -Eoq 'epair[0-9]+'; then for _num in $(seq 0 "${_bastille_if_num_range}"); do if ! echo "${_bastille_if_list}" | grep -oqswx "${_num}"; 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}" @@ -224,6 +239,7 @@ update_jailconf_vnet() { local _new_host_epair="epair${_num}a" local _new_jail_epair="epair${_num}b" fi + # 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}")" @@ -232,18 +248,22 @@ update_jailconf_vnet() { _target_host_epair="${_if}a" _target_jail_epair="${_if}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 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}')" @@ -251,8 +271,10 @@ 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 description sed -i '' "/${_new_host_epair}/ 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]+")" local _jail_vnet_vlan="$(grep "vlans_${_jail_vnet}" "${_rc_conf}" | sed 's/.*=//g')" @@ -281,17 +303,21 @@ update_jailconf_vnet() { break fi done + # Update VNET (non-bridged) config elif echo ${_if} | grep -Eoq 'e[0-9]+b_bastille[0-9]+'; then + # Update VNET config _if="$(echo ${_if} | grep -Eo 'bastille[0-9]+')" for _num in $(seq 0 "${_bastille_if_num_range}"); do if ! echo "${_bastille_if_list}" | grep -oqswx "${_num}"; then + # Update jail.conf epair name local _jail_if="bastille${_num}" local _jail_vnet="$(grep ${_if} "${_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" local _jail_vnet_vlan="$(grep "vlans_${_jail_vnet}" "${_rc_conf}" | sed 's/.*=//g')" sed -i '' "s|${_if}|${_jail_if}|g" "${_jail_conf}" + # If jail had a static MAC, generate one for clone if grep ether ${_jail_conf} | grep -qoc ${_jail_if}; then local external_interface="$(grep ${_jail_if} ${_jail_conf} | grep -o 'addm.*' | awk '{print $3}' | sed 's/["|;]//g')" @@ -300,6 +326,7 @@ update_jailconf_vnet() { sed -i '' "s|${_jail_if} ether.*:.*:.*:.*:.*:.*b\";|${_jail_if} ether ${macaddr}b\";|" "${_jail_conf}" fi sed -i '' "/${_jail_if}/ 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_${_jail_if}_name|" "${_rc_conf}" if grep "vnet0" "${_rc_conf}" | grep -q ${_jail_if}; then @@ -325,23 +352,27 @@ update_jailconf_vnet() { fi break fi - done + done + # Update netgraph VNET (non-bridged) config elif echo ${_if} | grep -Eoq 'ng[0-9]+_bastille[0-9]+'; then _if="$(echo ${_if} | grep -Eo 'bastille[0-9]+')" for _num in $(seq 0 "${_bastille_if_num_range}"); do if ! echo "${_bastille_if_list}" | grep -oqswx "${_num}"; then + # Update jail.conf epair name local _jail_if="bastille${_num}" local _jail_vnet="$(grep ${_if} "${_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")" local _jail_vnet_vlan="$(grep "vlans_${_jail_vnet}" "${_rc_conf}" | sed 's/.*=//g')" sed -i '' "s|${_if}|${_jail_if}|g" "${_jail_conf}" + # If jail had a static MAC, generate one for clone if grep ether ${_jail_conf} | grep -qoc ${_jail_if}; then local external_interface="$(grep ${_jail_if} ${_jail_conf} | grep -o 'jng bridge.*' | awk '{print $4}' | sed 's/["|;]//g')" generate_static_mac "${NEWNAME}" "${external_interface}" sed -i '' "s|${_jail_if} ether.*:.*:.*:.*:.*:.*a\";|${_jail_if} ether ${macaddr}a\";|" "${_jail_conf}" fi + # Update /etc/rc.conf sed -i '' "s|ifconfig_ng0_${_if}_name|ifconfig_ng0_${_jail_if}_name|" "${_rc_conf}" if grep "vnet0" "${_rc_conf}" | grep -q ${_jail_if}; then @@ -374,22 +405,31 @@ update_jailconf_vnet() { clone_jail() { - info "\n[${TARGET}]:" - echo "Attempting clone to ${NEWNAME}..." - if ! [ -d "${bastille_jailsdir}/${NEWNAME}" ]; then + if checkyesno bastille_zfs_enable; then + + # Validate jail state 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 [ "${AUTO}" -eq 1 ]; then - echo "Auto-stopping ${TARGET}..." + if ! check_target_is_running "${TARGET}"; then + error_exit "[ERROR]: [-l|--live] can only be used with a running jail." + fi + elif ! check_target_is_stopped "${TARGET}"; then + if [ "${AUTO}" -eq 1 ]; then bastille stop "${TARGET}" else + info "\n[${TARGET}]:" error_notify "Jail is running." error_exit "Use [-a|--auto] to force stop the jail, or [-l|--live] (ZFS only) to clone a running jail." fi fi + if [ -n "${IP}" ]; then + validate_ip "${IP}" + else + usage + fi + if [ -n "${bastille_zfs_zpool}" ]; then # Replicate the existing container DATE=$(date +%F-%H%M%S) @@ -404,12 +444,13 @@ clone_jail() { zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NEWNAME}/root@bastille_clone_${DATE}" zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NEWNAME}@bastille_clone_${DATE}" fi + else check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-stopping ${TARGET}..." bastille stop "${TARGET}" else + info "\n[${TARGET}]:" error_notify "Jail is running." error_exit "Use [-a|--auto] to force stop the jail." fi @@ -419,7 +460,7 @@ clone_jail() { fi else - error_exit "${NEWNAME} already exists." + error_exit "[ERROR]: ${NEWNAME} already exists." fi # Generate jail configuration files @@ -428,9 +469,9 @@ clone_jail() { # Display exit status if [ "$?" -ne 0 ]; then - error_exit "An error has occurred while attempting to clone '${TARGET}'." + error_exit "[ERROR]: An error has occurred while attempting to clone '${TARGET}'." else - info "Cloned '${TARGET}' to '${NEWNAME}' successfully." + info "\nCloned '${TARGET}' to '${NEWNAME}' successfully." fi # Start jails if AUTO=1 or LIVE=1 @@ -442,12 +483,7 @@ clone_jail() { fi } -# Check if IP address is valid. -if [ -n "${IP}" ]; then - validate_ip -else - usage -fi +info "\nAttempting to clone '${TARGET}' to '${NEWNAME}'..." clone_jail diff --git a/usr/local/share/bastille/cmd.sh b/usr/local/share/bastille/cmd.sh index fc689ab5..1dc69d91 100644 --- a/usr/local/share/bastille/cmd.sh +++ b/usr/local/share/bastille/cmd.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 "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -76,7 +76,7 @@ while [ "$#" -gt 0 ]; do esac done -if [ $# -eq 0 ]; then +if [ "$#" -eq 0 ]; then usage fi @@ -91,27 +91,32 @@ set_target "${TARGET}" for _jail in ${JAILS}; do - info "\n[${_jail}]:" - + # Validate jail state check_target_is_running "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-starting ${_jail}..." bastille start "${_jail}" else + info "\n[${_jail}]:" error_notify "Jail is not running." error_continue "Use [-a|--auto] to auto-start the jail." fi - + + info "\n[${_jail}]:" + COUNT=$(($COUNT+1)) + + # Allow executing commands on linux jails if grep -qw "linsysfs" "${bastille_jailsdir}/${_jail}/fstab"; then - # Allow executing commands on Linux jails. jexec -l -u root "${_jail}" "$@" else jexec -l -U root "${_jail}" "$@" fi + ERROR_CODE=$? + if [ "${ERROR_CODE}" -ne 0 ]; then warn "[${_jail}]: ${ERROR_CODE}" fi + if [ "$COUNT" -eq 1 ]; then RETURN=${ERROR_CODE} else @@ -124,6 +129,4 @@ done if [ "${COUNT}" -gt 1 ] && [ "${RETURN}" -gt 0 ]; then RETURN=1 return "${RETURN}" -fi - -echo +fi \ No newline at end of file diff --git a/usr/local/share/bastille/config.sh b/usr/local/share/bastille/config.sh index e46cc3ca..de1019b9 100644 --- a/usr/local/share/bastille/config.sh +++ b/usr/local/share/bastille/config.sh @@ -65,7 +65,7 @@ while [ "$#" -gt 0 ]; do shift ;; -*) - error_notify "Unknown Option: \"${1}\"" + error_notify "[ERROR]: Unknown Option: \"${1}\"" usage ;; *) @@ -115,12 +115,13 @@ print_jail_conf() { } for _jail in ${JAILS}; do + # Handle Bastille specific properties + # Currently only 'priority' and 'boot' if [ "${PROPERTY}" = "priority" ] || [ "${PROPERTY}" = "prio" ]; then PROPERTY="priority" BASTILLE_PROPERTY=1 FILE="${bastille_jailsdir}/${_jail}/boot.conf" - info "[${_jail}]:" if [ "${ACTION}" = "set" ]; then if echo "${VALUE}" | grep -Eq '^[0-9]+$'; then sysrc -f "${FILE}" "${PROPERTY}=${VALUE}" @@ -133,7 +134,6 @@ for _jail in ${JAILS}; do elif [ "${PROPERTY}" = "boot" ]; then BASTILLE_PROPERTY=1 FILE="${bastille_jailsdir}/${_jail}/boot.conf" - info "[${_jail}]:" if [ "${ACTION}" = "set" ]; then if [ "${VALUE}" = "on" ] || [ "${VALUE}" = "off" ]; then sysrc -f "${FILE}" "${PROPERTY}=${VALUE}" @@ -244,4 +244,4 @@ if { [ "${ACTION}" = "set" ] || [ "${ACTION}" = "remove" ]; } && [ -z "${BASTILL info "A restart is required for the changes to be applied. See 'bastille restart'." fi -exit 0 +exit 0 \ No newline at end of file diff --git a/usr/local/share/bastille/console.sh b/usr/local/share/bastille/console.sh index 45911e1b..d90be987 100644 --- a/usr/local/share/bastille/console.sh +++ b/usr/local/share/bastille/console.sh @@ -65,7 +65,7 @@ while [ "$#" -gt 0 ]; do case ${_opt} in x) enable_debug ;; a) AUTO=1 ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -87,8 +87,10 @@ bastille_root_check set_target "${TARGET}" validate_user() { + local _jail="${1}" local _user="${2}" + if jexec -l "${_jail}" id "${_user}" >/dev/null 2>&1; then USER_SHELL="$(jexec -l "${_jail}" getent passwd "${_user}}" | cut -d: -f7)" if [ -n "${USER_SHELL}" ]; then @@ -106,27 +108,33 @@ validate_user() { } check_fib() { + local _jail="${1}" + fib=$(grep 'exec.fib' "${bastille_jailsdir}/${_jail}/jail.conf" | awk '{print $3}' | sed 's/\;//g') - if [ -n "${fib}" ]; then - _setfib="setfib -F ${fib}" - else - _setfib="" - fi + + if [ -n "${fib}" ]; then + _setfib="setfib -F ${fib}" + else + _setfib="" + fi } + for _jail in ${JAILS}; do - info "\n[${_jail}]:" - + # Validate jail state check_target_is_running "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-starting ${_jail}..." bastille start "${_jail}" else + info "\n[${_jail}]:" error_notify "Jail is not running." error_continue "Use [-a|--auto] to auto-start the jail." fi + + info "\n[${_jail}]:" LOGIN="$(jexec -l "${_jail}" which login)" + if [ -n "${USER}" ]; then validate_user "${_jail}" "${USER}" else @@ -135,6 +143,4 @@ for _jail in ${JAILS}; do ${_setfib} jexec -l "${_jail}" $LOGIN -f root fi -done - -echo \ No newline at end of file +done \ No newline at end of file diff --git a/usr/local/share/bastille/convert.sh b/usr/local/share/bastille/convert.sh index 60014b21..5a1bf641 100644 --- a/usr/local/share/bastille/convert.sh +++ b/usr/local/share/bastille/convert.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 "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -82,24 +82,26 @@ CONVERT_RELEASE="${2}" bastille_root_check set_target_single "${TARGET}" -info "\n[${TARGET}]:" - +# Validate jail state check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-stopping ${TARGET}..." bastille stop "${TARGET}" -else +else + info "\n[${TARGET}]:" error_notify "Jail is running." error_exit "Use [-a|--auto] to auto-stop the jail." fi validate_release_name() { + local _name=${1} local _sanity="$(echo "${_name}" | tr -c -d 'a-zA-Z0-9-_')" + if [ -n "$(echo "${_sanity}" | awk "/^[-_].*$/" )" ]; then - error_exit "Release names may not begin with (-|_) characters!" + error_exit "[ERROR]: Release names may not begin with (-|_) characters!" elif [ "${_name}" != "${_sanity}" ]; then - error_exit "Release names may not contain special characters!" + error_exit "[ERROR]: Release names may not contain special characters!" fi + } convert_jail_to_release() { @@ -107,7 +109,7 @@ convert_jail_to_release() { _jailname="${1}" _release="${2}" - echo "Creating ${_release} from ${_jailname}..." + info "\nAttempting to create '${_release}' from '${_jailname}'..." if checkyesno bastille_zfs_enable; then if [ -n "${bastille_zfs_zpool}" ]; then @@ -140,7 +142,7 @@ convert_jail_to_release() { zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${_release}" error_exit "Failed to create release. Please retry!" else - info "Created ${_release} from ${_jailname}" + info "\nCreated '${_release}' from '${_jailname}'\n" fi else ## copy all files for thick jails @@ -148,14 +150,15 @@ convert_jail_to_release() { if [ "$?" -ne 0 ]; then ## notify and clean stale files/directories bastille destroy -af "${NAME}" - error_exit "Failed to create release. Please retry!" + error_exit "[ERROR]: Failed to create release. Please retry!" else - info "Created ${_release} from ${_jailname}" + info "\nCreated '${_release}' from '${_jailname}'\n" fi fi } convert_symlinks() { + # Work with the symlinks, revert on first cp error if [ -d "${bastille_releasesdir}/${RELEASE}" ]; then # Retrieve old symlinks temporarily @@ -166,7 +169,7 @@ convert_symlinks() { done # Copy new files to destination jail - echo "Copying required base files to container..." + info "\nCopying required base files to container..." for _link in ${SYMLINKS}; do if [ ! -d "${_link}" ]; then if [ -d "${bastille_releasesdir}/${RELEASE}/${_link}" ]; then @@ -185,13 +188,13 @@ convert_symlinks() { fi done else - error_exit "Release must be bootstrapped first. See 'bastille bootstrap'." + error_exit "[ERROR]: Release must be bootstrapped first. See 'bastille bootstrap'." fi } revert_convert() { # Revert the conversion on first cp error - error_notify "A problem has occurred while copying the files. Reverting changes..." + error_notify "[ERROR]: A problem has occurred while copying the files. Reverting changes..." for _link in ${SYMLINKS}; do if [ -d "${_link}" ]; then chflags -R noschg "${bastille_jailsdir}/${TARGET}/root/${_link}" @@ -209,10 +212,13 @@ revert_convert() { } start_convert() { + # Attempt container conversion and handle some errors DATE=$(date) + if [ -d "${bastille_jailsdir}/${TARGET}" ]; then - info "Converting '${TARGET}' into a thickjail. This may take a while..." + + info "\nConverting '${TARGET}' into a thickjail. This may take a while..." # Set some variables RELEASE=$(grep -w "${bastille_releasesdir}/.* ${bastille_jailsdir}/${TARGET}/root/.bastille" ${bastille_jailsdir}/${TARGET}/fstab | sed "s|${bastille_releasesdir}/||;s| .*||") @@ -230,53 +236,56 @@ start_convert() { sed -i '' -E "s|${FSTABMOD}|# Converted from thin to thick container on ${DATE}|g" "${bastille_jailsdir}/${TARGET}/fstab" if [ -n "${HASPORTS}" ]; then sed -i '' -E "s|${HASPORTS}|# Ports copied from base to container on ${DATE}|g" "${bastille_jailsdir}/${TARGET}/fstab" - info "Copying ports to container..." + info "\nCopying ports to container..." cp -a "${bastille_releasesdir}/${RELEASE}/usr/ports" "${bastille_jailsdir}/${TARGET}/root/usr" fi mv "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/root/.bastille.old" - info "Conversion of '${TARGET}' completed successfully!" + info "\nConversion of '${TARGET}' completed successfully!\n" exit 0 else - error_exit "Can't determine release version. See 'bastille bootstrap'." + error_exit "[ERROR]: Can't determine release version. See 'bastille bootstrap'." fi else - error_exit "${TARGET} not found. See 'bastille create'." + error_exit "[ERROR]: ${TARGET} not found. See 'bastille create'." fi } # Convert thin jail to thick jail if only one arg # Convert jail to release if two args if [ "$#" -eq 1 ]; then + # Check if jail is a thin jail if [ ! -d "${bastille_jailsdir}/${TARGET}/root/.bastille" ]; then - error_exit "${TARGET} is not a thin container." + error_exit "[ERROR]: ${TARGET} is not a thin container." elif ! grep -qw ".bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then - error_exit "${TARGET} is not a thin container." + error_exit "[ERROR]: ${TARGET} is not a thin container." fi + # Make sure the user agree with the conversion # Be interactive here since this cannot be easily undone while :; do - error_notify "Warning: container conversion from thin to thick can't be undone!" + warn "\n[WARNING]: Jail conversion from thin to thick can't be undone!\n" # shellcheck disable=SC2162 # shellcheck disable=SC3045 read -p "Do you really wish to convert '${TARGET}' into a thick container? [y/N]:" yn case ${yn} in - [Yy]) start_convert;; - [Nn]) exit 0;; + [Yy]) start_convert;; + [Nn]) exit 0;; esac done + elif [ "$#" -eq 2 ]; then + # Check if jail is a thick jail if [ -d "${bastille_jailsdir}/${TARGET}/root/.bastille" ]; then - error_exit "${TARGET} is not a thick jail." + error_exit "[ERROR]: ${TARGET} is not a thick jail." elif grep -qw ".bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then - error_exit "${TARGET} is not a thick jail." + error_exit "[ERROR]: ${TARGET} is not a thick jail." fi + validate_release_name "${CONVERT_RELEASE}" convert_jail_to_release "${TARGET}" "${CONVERT_RELEASE}" else usage -fi - -echo +fi \ No newline at end of file diff --git a/usr/local/share/bastille/cp.sh b/usr/local/share/bastille/cp.sh index edbdba18..2853ea07 100644 --- a/usr/local/share/bastille/cp.sh +++ b/usr/local/share/bastille/cp.sh @@ -65,7 +65,7 @@ while [ "$#" -gt 0 ]; do case ${_opt} in q) OPTION="-a" ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -95,7 +95,7 @@ for _jail in ${JAILS}; do 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}" + error_continue "[ERROR]: CP failed: ${host_path} -> ${jail_path}" fi done diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index e8ebf791..f43c5afb 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -37,6 +37,7 @@ usage() { # If no option specified, will create a thin container by default error_notify "Usage: bastille create [option(s)] NAME RELEASE IP_ADDRESS [INTERFACE]" cat << EOF + Options: -B | --bridge Enables VNET, VNET containers are attached to a specified, already existing external bridge. @@ -59,26 +60,35 @@ EOF } validate_name() { + local NAME_VERIFY=${NAME} 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!" + error_exit "[ERROR]: Jail names may not begin with (-|_) characters!" elif [ "${NAME_VERIFY}" != "${NAME_SANITY}" ]; then - error_exit "Container names may not contain special characters!" + error_exit "[ERROR]: Jail names may not contain special characters!" elif echo "${NAME_VERIFY}" | grep -qE '^[0-9]+$'; then - error_exit "Container names may not contain only digits." + error_exit "[ERROR]: Jail names may not contain only digits." fi } validate_ip() { + _ip="${1}" _ip6=$(echo "${_ip}" | grep -E '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$)|SLAAC)') + if [ -n "${_ip6}" ]; then - info "Valid: (${_ip6})." + + info "\nValid: (${_ip6})." + ipx_addr="ip6.addr" + else if [ "${_ip}" = "inherit" ] || [ "${_ip}" = "ip_hostname" ] || [ "${_ip}" = "DHCP" ] || [ "${_ip}" = "SYNCDHCP" ]; then - info "Valid: (${_ip})." + + info "\nValid: (${_ip})." + else local IFS if echo "${_ip}" | grep -Eq '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))?$'; then @@ -90,16 +100,19 @@ validate_ip() { error_continue "Invalid: (${TEST_IP})" fi done - if ifconfig | grep -qwF "${TEST_IP}"; then - warn "Warning: IP address already in use (${TEST_IP})." - fi ipx_addr="ip4.addr" - info "Valid: (${_ip})." + info "\nValid: (${_ip})." else error_continue "Invalid: (${_ip})." fi fi fi + + # Warn if IP is in use + if ifconfig | grep -qwF "${TEST_IP}"; then + warn "[WARNING]: IP address in use (${TEST_IP})." + fi + # Set interface value if [ ! -f "${bastille_jail_conf}" ]; then if [ -z "${bastille_network_loopback}" ] && [ -n "${bastille_network_shared}" ]; then @@ -112,6 +125,7 @@ validate_ip() { local bastille_jail_conf_interface=${INTERFACE} fi fi + # Determine IP/Interface mode if [ "${_ip}" = "inherit" ]; then if [ -n "${DUAL_STACK}" ]; then @@ -148,27 +162,32 @@ validate_ip() { } validate_ips() { + IP6_MODE="disable" IP4_DEFINITION="" IP6_DEFINITION="" IP4_ADDR="" IP6_ADDR="" IP_HOSTNAME="" + for ip in ${IP}; do validate_ip "${ip}" done } validate_netif() { + local LIST_INTERFACES="$(ifconfig -l)" + if echo "${LIST_INTERFACES} VNET" | grep -qwo "${INTERFACE}"; then - info "Valid: (${INTERFACE})." + info "\nValid: (${INTERFACE})." else - error_exit "Invalid: (${INTERFACE})." + error_exit "[ERROR]: Invalid: (${INTERFACE})." fi } validate_release() { + ## ensure the user set the Linux(experimental) option explicitly if [ -n "${UBUNTU}" ]; then if [ -z "${LINUX_JAIL}" ]; then @@ -185,6 +204,7 @@ validate_release() { } generate_minimal_conf() { + cat << EOF > "${bastille_jail_conf}" ${NAME} { host.hostname = ${NAME}; @@ -196,6 +216,7 @@ EOF } generate_jail_conf() { + if [ "$(sysctl -n security.jail.jailed)" -eq 1 ]; then devfs_ruleset_value=0 else @@ -224,6 +245,7 @@ EOF } generate_linux_jail_conf() { + cat << EOF > "${bastille_jail_conf}" ${NAME} { host.hostname = ${NAME}; @@ -247,12 +269,15 @@ EOF } generate_vnet_jail_conf() { + if [ "$(sysctl -n security.jail.jailed)" -eq 1 ]; then devfs_ruleset_value=0 else devfs_ruleset_value=13 fi + NETBLOCK=$(generate_vnet_jail_netblock "${NAME}" "${VNET_JAIL_BRIDGE}" "${bastille_jail_conf_interface}" "${STATIC_MAC}") + cat << EOF > "${bastille_jail_conf}" ${NAME} { enforce_statfs = 2; @@ -274,6 +299,7 @@ EOF } post_create_jail() { + # Common config checks and settings. # Using relative paths here. @@ -310,6 +336,7 @@ post_create_jail() { } create_jail() { + bastille_jail_base="${bastille_jailsdir}/${NAME}/root/.bastille" ## dir bastille_jail_template="${bastille_jailsdir}/${NAME}/root/.template" ## dir bastille_jail_path="${bastille_jailsdir}/${NAME}/root" ## dir @@ -424,7 +451,7 @@ create_jail() { if ! cp -a "${bastille_releasesdir}/${RELEASE}/${files}" "${bastille_jail_path}/${files}"; then ## notify and clean stale files/directories bastille destroy -af "${NAME}" - error_exit "Failed to copy release files. Please retry create!" + error_exit "[ERROR]: Failed to copy release files. Please retry create!" fi fi done @@ -444,9 +471,10 @@ create_jail() { # Check and apply required settings. post_create_jail elif [ -n "${THICK_JAIL}" ]; then - info "\nCreating a thickjail. This may take a while...\n" - ## perform release base replication + info "\nCreating a thickjail. This may take a while..." + + ## perform release base replication ## sane bastille zfs options ZFS_OPTIONS=$(echo ${bastille_zfs_options} | sed 's/-o//g') ## send without -R if encryption is enabled @@ -478,7 +506,7 @@ create_jail() { if [ "$?" -ne 0 ]; then ## notify and clean stale files/directories bastille destroy -af "${NAME}" - error_exit "Failed release base replication. Please retry create!" + error_exit "[ERROR]: Failed release base replication. Please retry create!" fi fi else @@ -487,7 +515,7 @@ create_jail() { if [ "$?" -ne 0 ]; then ## notify and clean stale files/directories bastille destroy -af "${NAME}" - error_exit "Failed to copy release files. Please retry create!" + error_exit "[ERROR]: Failed to copy release files. Please retry create!" fi fi fi @@ -549,8 +577,8 @@ create_jail() { chmod 0700 "${bastille_jailsdir}/${NAME}" # Apply priority and boot settings before starting jail - sysrc -f "${bastille_jailsdir}/${NAME}/boot.conf" boot=${BOOT} - sysrc -f "${bastille_jailsdir}/${NAME}/boot.conf" priority="${PRIORITY}" + sysrc -f "${bastille_jailsdir}/${NAME}/boot.conf" boot=${BOOT} >/dev/null + sysrc -f "${bastille_jailsdir}/${NAME}/boot.conf" priority="${PRIORITY}" >/dev/null # Jail must be started before applying the default template. -- cwells if [ -z "${EMPTY_JAIL}" ]; then @@ -566,7 +594,7 @@ create_jail() { if [ -z "${EMPTY_JAIL}" ]; then if ! check_target_is_running "${NAME}"; then bastille destroy -af "${NAME}" - error_exit "[${NAME}]: Failed to create jail..." + error_exit "[ERROR]: Failed to create jail: ${NAME}" fi fi @@ -579,6 +607,7 @@ create_jail() { _gateway6='' _ifconfig_inet='' _ifconfig_inet6='' + if echo "${IP}" | grep -qE '(0[.]0[.]0[.]0|DHCP)'; then # Enable DHCP if requested _ifconfig_inet=SYNCDHCP @@ -637,7 +666,7 @@ create_jail() { fi ## Using templating function to fetch necessary packges @hackacad elif [ -n "${LINUX_JAIL}" ]; then - info "Fetching packages..." + info "\nFetching packages..." jexec -l "${NAME}" /bin/bash -c "DEBIAN_FRONTEND=noninteractive rm /var/cache/apt/archives/rsyslog*.deb" jexec -l "${NAME}" /bin/bash -c "DEBIAN_FRONTEND=noninteractive dpkg --force-depends --force-confdef --force-confold -i /var/cache/apt/archives/*.deb" jexec -l "${NAME}" /bin/bash -c "DEBIAN_FRONTEND=noninteractive dpkg --force-depends --force-confdef --force-confold -i /var/cache/apt/archives/*.deb" @@ -764,7 +793,7 @@ while [ $# -gt 0 ]; do T) THICK_JAIL=1 ;; V) VNET_JAIL=1 ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -778,16 +807,16 @@ done # Validate options if [ -n "${EMPTY_JAIL}" ]; then if [ -n "${CLONE_JAIL}" ] || [ -n "${THICK_JAIL}" ] || [ -n "${VNET_JAIL}" ] || [ -n "${LINUX_JAIL}" ]; then - error_exit "Error: Empty jail option can't be used with other options." + error_exit "[ERROR]: Empty jail option can't be used with other options." fi elif [ -n "${LINUX_JAIL}" ]; then if [ -n "${EMPTY_JAIL}" ] || [ -n "${VNET_JAIL}" ] || [ -n "${THICK_JAIL}" ] || [ -n "${CLONE_JAIL}" ]; then - error_exit "Error: Linux jail option can't be used with other options." + error_exit "[ERROR]: Linux jail option can't be used with other options." fi elif [ -n "${CLONE_JAIL}" ] && [ -n "${THICK_JAIL}" ]; then - error_exit "Error: Clonejail and Thickjail can't be used together." + error_exit "[ERROR]: Clonejail and Thickjail can't be used together." elif [ -z "${VNET_JAIL}" ] && [ -z "${VNET_JAIL_BRIDGE}" ] && [ -n "${VLAN_ID}" ]; then - error_exit "Error: VLANs can only be used with VNET and bridged VNET jails." + error_exit "[ERROR]: VLANs can only be used with VNET and bridged VNET jails." fi NAME="$1" @@ -795,6 +824,8 @@ RELEASE="$2" IP="$3" INTERFACE="$4" +info "\nAttempting to create jail: ${NAME}" + if [ -n "${EMPTY_JAIL}" ]; then if [ $# -ne 1 ]; then usage @@ -805,7 +836,7 @@ else fi fi -## validate jail name +# Validate jail name if [ -n "${NAME}" ]; then validate_name fi @@ -813,11 +844,11 @@ fi # Validate interface type if [ -n "${VNET_JAIL}" ] && [ -n "${VNET_JAIL_BRIDGE}" ]; then if ! ifconfig -g bridge | grep -owq "${INTERFACE}"; then - error_exit "Interface is not a bridge: ${INTERFACE}" + error_exit "[ERROR]: Interface is not a bridge: ${INTERFACE}" fi elif [ -n "${VNET_JAIL}" ] && [ -z "${VNET_JAIL_BRIDGE}" ]; then if ifconfig -g bridge | grep -owq "${INTERFACE}"; then - error_exit "Interface is a bridge: ${INTERFACE}" + error_exit "[ERROR]: Interface is a bridge: ${INTERFACE}" fi fi @@ -853,7 +884,7 @@ if [ -n "${LINUX_JAIL}" ] && [ -n "${VALIDATE_RELEASE}" ]; then NAME_VERIFY=bookworm ;; *) - error_notify "Unknown Linux." + error_notify "[ERROR]: Unknown linux release." usage ;; esac @@ -937,24 +968,25 @@ if [ -z "${EMPTY_JAIL}" ]; then esac fi - ## check for name/root/.bastille + # Check for name/root/.bastille if [ -d "${bastille_jailsdir}/${NAME}/root/.bastille" ]; then - error_exit "Jail: ${NAME} already created. ${NAME}/root/.bastille exists." + error_exit "[ERROR]: ${NAME} already exists. ${NAME}/root/.bastille exists." fi - ## check for required release + # Check for required release if [ ! -d "${bastille_releasesdir}/${RELEASE}" ]; then - error_exit "Release must be bootstrapped first; see 'bastille bootstrap'." + error_notify "[ERROR]: Release must be bootstrapped first." + error_exit "See 'bastille bootstrap'." fi - ## check if ip address is valid + # Validate IP address if [ -n "${IP}" ]; then validate_ips else usage fi - ## check if interface is valid + # Validate interface if [ -n "${INTERFACE}" ]; then validate_netif validate_netconf @@ -962,7 +994,7 @@ if [ -z "${EMPTY_JAIL}" ]; then if [ -z "${INTERFACE}" ]; then if [ -z "${bastille_network_shared}" ]; then # User must specify interface on vnet jails. - error_exit "Error: Network interface not defined." + error_exit "[ERROR]: Network interface not defined." else validate_netconf fi @@ -1004,7 +1036,7 @@ if [ -z ${bastille_template_vnet+x} ]; then fi if check_target_exists "${NAME}"; then - error_exit "Error: Existing jail found: ${NAME}" + error_exit "[ERROR]: Jail already exists: ${NAME}" fi create_jail "${NAME}" "${RELEASE}" "${IP}" "${INTERFACE}" diff --git a/usr/local/share/bastille/destroy.sh b/usr/local/share/bastille/destroy.sh index 97f53fcb..bb73ddd5 100644 --- a/usr/local/share/bastille/destroy.sh +++ b/usr/local/share/bastille/destroy.sh @@ -53,27 +53,32 @@ destroy_jail() { for _jail in ${JAILS}; do - info "[${_jail}]:" - bastille_jail_base="${bastille_jailsdir}/${_jail}" bastille_jail_log="${bastille_logsdir}/${_jail}_console.log" + # Validate jail state before continuing check_target_is_stopped "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-stopping ${_jail}..." bastille stop "${_jail}" else + info "\n[${_jail}]:" error_notify "Jail is running." error_continue "Use [-a|--auto] to auto-stop the jail." fi + info "\n[${_jail}]:" + if [ -d "${bastille_jail_base}" ]; then + # Make sure no filesystem is currently mounted mount_points="$(mount | cut -d ' ' -f 3 | grep ${bastille_jail_base}/root/)" + if [ -n "${mount_points}" ]; then - error_notify "Failed to destroy jail: ${_jail}" - error_continue_next_jail "Jail has mounted filesystems:\n$mount_points" + error_notify "[ERROR]: Failed to destroy jail: ${_jail}" + error_continue "Jail has mounted filesystems:\n$mount_points" fi - info "Deleting Jail: ${_jail}." + + echo "Destroying jail..." + if checkyesno bastille_zfs_enable; then if [ -n "${bastille_zfs_zpool}" ]; then if [ -n "${_jail}" ]; then @@ -85,7 +90,7 @@ destroy_jail() { # This will deal with the common "cannot unmount 'XYZ': pool or dataset is busy" # unless the force option is defined by the user, otherwise will have a partially deleted jail. if ! zfs destroy "${OPTIONS}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}"; then - error_continue_next_jail "[ERROR]: Jail dataset(s) appears to be busy, exiting." + error_continue "[ERROR]: Jail dataset(s) appears to be busy, exiting." fi fi fi @@ -102,13 +107,13 @@ destroy_jail() { # Archive jail log if [ -f "${bastille_jail_log}" ]; then mv "${bastille_jail_log}" "${bastille_jail_log}"-"$(date +%F)" - info "Note: jail console logs archived." - info "${bastille_jail_log}-$(date +%F)" + echo "Note: jail console logs archived." + echo "${bastille_jail_log}-$(date +%F)" fi # Clear any active rdr rules if [ ! -z "$(pfctl -a "rdr/${_jail}" -Psn 2>/dev/null)" ]; then - info "Clearing RDR rules:" + echo "Clearing RDR rules..." pfctl -a "rdr/${_jail}" -Fn fi fi @@ -129,13 +134,18 @@ destroy_rel() { bastille_rel_base="${bastille_releasesdir}/${TARGET}" ## dir + info "\nAttempting to destroy release: ${TARGET}" + ## check if this release have containers child BASE_HASCHILD="0" if [ -d "${bastille_jailsdir}" ]; then + JAIL_LIST=$(ls "${bastille_jailsdir}" | sed "s/\n//g") + for _jail in ${JAIL_LIST}; do + if grep -qwo "${TARGET}" "${bastille_jailsdir}/${_jail}/fstab" 2>/dev/null; then - error_notify "Notice: (${_jail}) depends on ${TARGET} base." + error_notify "[ERROR]: (${_jail}) depends on ${TARGET} base." BASE_HASCHILD="1" elif checkyesno bastille_zfs_enable; then if [ -n "${bastille_zfs_zpool}" ]; then @@ -147,7 +157,7 @@ destroy_rel() { CLONE_JAIL=$(zfs list -H -o clones "${_snap_clone}" | tr ',' '\n') CLONE_CHECK="${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}/root" if echo "${CLONE_JAIL}" | grep -qw "${CLONE_CHECK}"; then - error_notify "Notice: (${_jail}) depends on ${TARGET} base." + error_notify "[ERROR]: (${_jail}) depends on ${TARGET} base." BASE_HASCHILD="1" fi fi @@ -159,10 +169,10 @@ destroy_rel() { fi if [ ! -d "${bastille_rel_base}" ]; then - error_exit "Release base not found." + error_exit "[ERROR]: Release base not found." else if [ "${BASE_HASCHILD}" -eq "0" ]; then - info "Deleting base: ${TARGET}" + echo "Deleting release base..." if checkyesno bastille_zfs_enable; then if [ -n "${bastille_zfs_zpool}" ]; then if [ -n "${TARGET}" ]; then @@ -195,7 +205,7 @@ destroy_rel() { fi fi else - error_notify "Cannot destroy base with child containers." + error_notify "[ERROR]: Cannot destroy base with child containers." fi fi } @@ -232,7 +242,7 @@ while [ "$#" -gt 0 ]; do c) NO_CACHE=1 ;; f) FORCE=1 ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -305,4 +315,4 @@ case "${TARGET}" in ;; esac -echo +echo \ No newline at end of file diff --git a/usr/local/share/bastille/edit.sh b/usr/local/share/bastille/edit.sh index 2c963db9..60a6ef4f 100644 --- a/usr/local/share/bastille/edit.sh +++ b/usr/local/share/bastille/edit.sh @@ -55,7 +55,7 @@ while [ "$#" -gt 0 ]; do shift ;; -*) - error_notify "Unknown Option: \"${1}\"" + error_notify "[ERROR]: Unknown Option: \"${1}\"" usage ;; *) @@ -82,4 +82,4 @@ if [ -z "${EDITOR}" ]; then EDITOR=edit fi -"${EDITOR}" "${bastille_jailsdir}/${TARGET}/${TARGET_FILENAME}" +"${EDITOR}" "${bastille_jailsdir}/${TARGET}/${TARGET_FILENAME}" \ No newline at end of file diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index 493af33f..a3cdbc7a 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -44,13 +44,15 @@ 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 [ -z "$(ls -A "${bastille_releasesdir}/${_release}/usr/src")" ]; then sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives=src 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}" + error_exit "[ERROR]: Failed to bootstrap etcupdate: ${_release}" else sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}" fi @@ -58,17 +60,19 @@ bootstrap_etc_release() { } bootstrap_etc_tarball() { + local _release="${1}" + if [ ! -f ${bastille_cachedir}/${_release}.tbz2 ]; then - echo "\nBuilding tarball, please wait..." + info "\nBuilding 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 "[ERROR]: Failed to build etcupdate tarball \"${_release}.tbz2\"" else info "\nEtcupdate 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..." + info "\nBuilding tarball, please wait..." if ! etcupdate build -d /tmp/etcupdate -s ${bastille_releasesdir}/${_release}/usr/src ${bastille_cachedir}/${_release}.tbz2; then error_exit "[ERROR]: Failed to build etcupdate tarball: ${_release}.tbz2" else @@ -80,34 +84,42 @@ bootstrap_etc_tarball() { } diff_review() { + local _jail="${1}" + if [ "${DRY_RUN}" -eq 1 ]; then error_exit "[ERROR]: diff mode does not support [-d|--dryrun]" fi - info "\n[${_jail}]: etcupdate --diff mode" + + echo "Running: etcupdate --diff mode" etcupdate diff -D "${bastille_jailsdir}/${_jail}/root" } resolve_conflicts() { + local _jail="${1}" + if [ "${DRY_RUN}" -eq 1 ]; then error_exit "[ERROR]: resolve mode does not support [-d|--dryrun]" fi - info "\n[${_jail}]: etcupdate resolve" + + echo "Running: etcupdate resolve" etcupdate resolve -D "${bastille_jailsdir}/${_jail}/root" } 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." + error_exit "[ERROR]: Please run 'bastille etcupdate bootstrap RELEASE' first." fi if [ "${DRY_RUN}" -eq 1 ]; then - info "\n[${_jail}]: etcupdate update --dry-run" + echo "Running: etcupdate update --dry-run" etcupdate -n -D "${bastille_jailsdir}/${_jail}/root" -t ${bastille_cachedir}/${_release}.tbz2 else - info "\n[${_jail}]: etcupdate update" + echo "Running: etcupdate update" etcupdate -D "${bastille_jailsdir}/${_jail}/root" -t ${bastille_cachedir}/${_release}.tbz2 fi } @@ -161,6 +173,7 @@ while [ "$#" -gt 0 ]; do usage else RELEASE="${2}" + info "\nAttempting to bootstrap etcupdate release: ${RELEASE}..." bootstrap_etc_release "${RELEASE}" bootstrap_etc_tarball "${RELEASE}" shift "$#" @@ -170,7 +183,11 @@ while [ "$#" -gt 0 ]; do TARGET="${1}" ACTION="${2}" RELEASE="${3}" + set_target_single "${TARGET}" + + info "\n[${TARGET}]:" + case "${ACTION}" in diff) diff_review "${TARGET}" @@ -189,11 +206,11 @@ while [ "$#" -gt 0 ]; do fi ;; *) - error_exit "Unknown action: \"${ACTION}\"" + error_exit "[ERROR]: Unknown action: \"${ACTION}\"" ;; esac ;; esac done -echo +echo \ No newline at end of file diff --git a/usr/local/share/bastille/export.sh b/usr/local/share/bastille/export.sh index 4a6ab0c3..34bbeb9b 100644 --- a/usr/local/share/bastille/export.sh +++ b/usr/local/share/bastille/export.sh @@ -119,7 +119,7 @@ if [ -n "${bastille_export_options}" ]; then -v|--verbose) OPT_ZSEND="-Rv" shift;; - -*) error_notify "Unknown Option: \"${1}\"" + -*) error_notify "[ERROR]: Unknown Option: \"${1}\"" usage;; esac done @@ -170,7 +170,7 @@ else shift ;; -*) - error_notify "Unknown Option: \"${1}\"" + error_notify "[ERROR]: Unknown Option: \"${1}\"" usage ;; *) @@ -194,13 +194,15 @@ fi bastille_root_check set_target_single "${TARGET}" +info "\n[${_jail}]:" + # Validate for combined options if [ "${COMP_OPTION}" -gt "1" ]; then - error_exit "Error: Only one compression format can be used during export." + error_exit "[ERROR]: Only one compression format can be used during export." fi if { [ -n "${TXZ_EXPORT}" ] || [ -n "${TGZ_EXPORT}" ]; } && [ -n "${SAFE_EXPORT}" ]; then - error_exit "Error: Simple archive modes with safe ZFS export can't be used together." + error_exit "[ERROR]: Simple archive modes with safe ZFS export can't be used together." fi if ! checkyesno bastille_zfs_enable; then @@ -209,7 +211,7 @@ if ! checkyesno bastille_zfs_enable; then [ -n "${RAW_EXPORT}" ] || [ -n "${SAFE_EXPORT}" ] || [ "${OPT_ZSEND}" = "-Rv" ]; then - error_exit "Options --xz, --gz, --raw, --safe, and --verbose are valid for ZFS configured systems only." + error_exit "[ERROR]: Options --xz, --gz, --raw, --safe, and --verbose are valid for ZFS configured systems only." fi fi @@ -226,7 +228,7 @@ if [ -n "${DIR_EXPORT}" ]; then # Set the user defined export directory bastille_backupsdir="${DIR_EXPORT}" else - error_exit "Error: Path not found." + error_exit "[ERROR]: Path not found." fi fi @@ -241,7 +243,7 @@ fi create_zfs_snap() { # Take a recursive temporary snapshot if [ -z "${USER_EXPORT}" ]; then - echo "Creating temporary ZFS snapshot for export..." + info "\nCreating temporary ZFS snapshot for export..." fi zfs snapshot -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_${TARGET}_${DATE}" } @@ -277,7 +279,7 @@ export_check() { EXPORT_INFO="to a compressed ${FILE_EXT} ${EXPORT_TYPE}" fi - info "${EXPORT_AS} '${TARGET}' ${EXPORT_INFO}..." + info "\n${EXPORT_AS} '${TARGET}' ${EXPORT_INFO}..." fi # Safely stop and snapshot the jail @@ -291,15 +293,13 @@ export_check() { if checkyesno bastille_zfs_enable; then if [ -z "${USER_EXPORT}" ]; then - info "Sending ZFS data stream..." + info "\nSending ZFS data stream..." fi fi } jail_export() { - info "\n[${_jail}]:" - # Attempt to export the container DATE=$(date +%F-%H%M%S) if checkyesno bastille_zfs_enable; then @@ -336,7 +336,7 @@ jail_export() { # Quietly export the container recursively, user must redirect standard output if ! zfs send ${OPT_ZSEND} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_${TARGET}_${DATE}"; then clean_zfs_snap - error_notify "\nError: An export option is required, see 'bastille export, otherwise the user must redirect to standard output." + error_exit "[ERROR]: An export option is required, see 'bastille export, otherwise the user must redirect to standard output." fi fi fi @@ -345,28 +345,28 @@ jail_export() { FILE_EXT=".tgz" # Create standard tgz backup archive - info "Exporting '${TARGET}' to a compressed ${FILE_EXT} archive..." + info "\nExporting '${TARGET}' to a compressed ${FILE_EXT} archive..." cd "${bastille_jailsdir}" && tar -cf - "${TARGET}" | gzip ${bastille_compress_gz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}" elif [ -n "${TXZ_EXPORT}" ]; then FILE_EXT=".txz" # Create standard txz backup archive - info "Exporting '${TARGET}' to a compressed ${FILE_EXT} archive..." + info "\nExporting '${TARGET}' to a compressed ${FILE_EXT} archive..." cd "${bastille_jailsdir}" && tar -cf - "${TARGET}" | xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}" else - error_exit "Error: export option required" + error_exit "[ERROR]: export option required" fi fi # shellcheck disable=SC2181 if [ "$?" -ne 0 ]; then - error_exit "Failed to export '${TARGET}' container." + error_exit "[ERROR]: Failed to export '${TARGET}' container." else if [ -z "${USER_EXPORT}" ]; then # Generate container checksum file cd "${bastille_backupsdir}" || error_exit "Failed to change directory." sha256 -q "${TARGET}_${DATE}${FILE_EXT}" > "${TARGET}_${DATE}.sha256" - info "Exported '${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}' successfully." + info "\nExported '${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}' successfully." fi exit 0 fi @@ -374,19 +374,20 @@ jail_export() { # Check if backups directory/dataset exist if [ ! -d "${bastille_backupsdir}" ]; then - error_exit "Backups directory/dataset does not exist. See 'bastille bootstrap'." + error_exit "[ERROR]: Backups directory/dataset does not exist. See 'bastille bootstrap'." fi if [ -n "${TARGET}" ]; then + if [ ! -d "${bastille_jailsdir}/${TARGET}" ]; then - error_exit "[${TARGET}]: Not found." + error_exit "[ERROR]: Jail not found: ${TARGET}" fi # Check if is a ZFS system if ! checkyesno bastille_zfs_enable; then # Check if container is running and ask for stop in non ZFS systems if [ -n "$(/usr/sbin/jls name | awk "/^${TARGET}$/")" ]; then - error_exit "${TARGET} is running. See 'bastille stop'." + error_exit "[ERROR]: ${TARGET} is running. See 'bastille stop'." fi fi jail_export diff --git a/usr/local/share/bastille/htop.sh b/usr/local/share/bastille/htop.sh index bc62d902..8626468a 100644 --- a/usr/local/share/bastille/htop.sh +++ b/usr/local/share/bastille/htop.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 "[ERROR]: Unknown Option: \"${1}\"" esac done shift @@ -85,18 +85,18 @@ TARGET="${1}" bastille_root_check set_target_single "${TARGET}" -info "[${TARGET}]:" - check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-starting ${TARGET}..." bastille start "${TARGET}" -else +else + info "\n[${TARGET}]:" error_notify "Jail is not running." - error_continue_next_jail "Use [-a|--auto] to auto-start the jail." + error_continue "Use [-a|--auto] to auto-start the jail." fi +info "\n[${TARGET}]:" + if [ ! -x "${bastille_jailsdir}/${TARGET}/root/usr/local/bin/htop" ]; then - error_notify "htop not found on ${TARGET}." + error_exit "[ERROR]: htop not found on ${TARGET}." elif [ -x "${bastille_jailsdir}/${TARGET}/root/usr/local/bin/htop" ]; then jexec -l ${TARGET} /usr/local/bin/htop -fi +fi \ No newline at end of file diff --git a/usr/local/share/bastille/import.sh b/usr/local/share/bastille/import.sh index c3c2d94d..cf9abda3 100644 --- a/usr/local/share/bastille/import.sh +++ b/usr/local/share/bastille/import.sh @@ -84,7 +84,7 @@ while [ "$#" -gt 0 ]; do M) OPT_STATIC_MAC=1 ;; v) OPT_ZRECV="-u -v" ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -117,20 +117,20 @@ validate_archive() { # Skip validation for unsupported archive if [ -f "${bastille_backupsdir}/${TARGET}" ]; then if [ -f "${bastille_backupsdir}/${FILE_TRIM}.sha256" ]; then - info "Validating file: ${TARGET}..." + info "\nValidating file: ${TARGET}..." SHA256_DIST=$(cat "${bastille_backupsdir}/${FILE_TRIM}.sha256") SHA256_FILE=$(sha256 -q "${bastille_backupsdir}/${TARGET}") if [ "${SHA256_FILE}" != "${SHA256_DIST}" ]; then - error_exit "Failed validation for ${TARGET}." + error_exit "[ERROR]: Failed validation for ${TARGET}." else - info "File validation successful!" + info "\nFile validation successful!" fi else # Check if user opt to force import if [ "${OPT_FORCE}" -eq 1 ]; then - warn "Warning: Skipping archive validation!" + warn "[WARNING]: Skipping archive validation!" else - error_exit "Checksum file not found. See 'bastille import [option(s)] FILE'." + error_exit "[ERROR]: Checksum file not found. See 'bastille import [option(s)] FILE'." fi fi fi @@ -141,7 +141,7 @@ update_zfsmount() { OLD_ZFS_MOUNTPOINT=$(zfs get -H mountpoint "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" | awk '{print $3}') NEW_ZFS_MOUNTPOINT="${bastille_jailsdir}/${TARGET_TRIM}/root" if [ "${NEW_ZFS_MOUNTPOINT}" != "${OLD_ZFS_MOUNTPOINT}" ]; then - info "Updating ZFS mountpoint..." + info "\nUpdating ZFS mountpoint..." zfs set mountpoint="${bastille_jailsdir}/${TARGET_TRIM}/root" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" fi @@ -155,11 +155,13 @@ update_zfsmount() { } update_jailconf() { + # Update jail.conf paths JAIL_CONFIG="${bastille_jailsdir}/${TARGET_TRIM}/jail.conf" + if [ -f "${JAIL_CONFIG}" ]; then if ! grep -qw "path = ${bastille_jailsdir}/${TARGET_TRIM}/root;" "${JAIL_CONFIG}"; then - info "Updating jail.conf..." + info "\nUpdating jail.conf..." sed -i '' "s|exec.consolelog.*=.*;|exec.consolelog = ${bastille_logsdir}/${TARGET_TRIM}_console.log;|" "${JAIL_CONFIG}" sed -i '' "s|path.*=.*;|path = ${bastille_jailsdir}/${TARGET_TRIM}/root;|" "${JAIL_CONFIG}" sed -i '' "s|mount.fstab.*=.*;|mount.fstab = ${bastille_jailsdir}/${TARGET_TRIM}/fstab;|" "${JAIL_CONFIG}" @@ -173,16 +175,18 @@ update_jailconf() { } update_fstab_import() { + # Update fstab .bastille mountpoint on thin containers only # Set some variables FSTAB_CONFIG="${bastille_jailsdir}/${TARGET_TRIM}/fstab" FSTAB_RELEASE=$(grep -owE '([1-9]{2,2})\.[0-9](-RELEASE|-RELEASE-i386|-RC[1-9])|([0-9]{1,2}-stable-build-[0-9]{1,3})|(current-build)-([0-9]{1,3})|(current-BUILD-LATEST)|([0-9]{1,2}-stable-BUILD-LATEST)|(current-BUILD-LATEST)' "${FSTAB_CONFIG}") FSTAB_CURRENT=$(grep -w ".*/releases/.*/jails/${TARGET_TRIM}/root/.bastille" "${FSTAB_CONFIG}") FSTAB_NEWCONF="${bastille_releasesdir}/${FSTAB_RELEASE} ${bastille_jailsdir}/${TARGET_TRIM}/root/.bastille nullfs ro 0 0" + if [ -n "${FSTAB_CURRENT}" ] && [ -n "${FSTAB_NEWCONF}" ]; then # If both variables are set, compare and update as needed if ! grep -qw "${bastille_releasesdir}/${FSTAB_RELEASE}.*${bastille_jailsdir}/${TARGET_TRIM}/root/.bastille" "${FSTAB_CONFIG}"; then - info "Updating fstab..." + info "\nUpdating fstab..." if [ -n "${RELEASE}" ]; then FSTAB_NEWCONF="${RELEASE}" fi @@ -192,9 +196,10 @@ update_fstab_import() { } generate_config() { + # Attempt to read previous config file and set required variables accordingly # If we can't get a valid interface, fallback to lo1 and warn user - info "Generating jail.conf..." + info "\nGenerating jail.conf..." DEVFS_RULESET=4 if [ "${FILE_EXT}" = ".zip" ]; then @@ -241,43 +246,43 @@ generate_config() { else # If there are multiple IP/NIC let the user configure network IP4_DEFINITION="" - IP6_DEFINITION="" + IP6_DEFINITION="" IP6_MODE="disable" - # IP4 set, but not IP6 + # IP4 set, but not IP6 if [ -n "${IP4_CONFIG}" ] && [ -z "${IP6_CONFIG}" ]; then if ! echo "${IP4_CONFIG}" | grep -q '.*,.*'; then IP4_IF=$(echo "${IP4_CONFIG}" | grep '.*|' | sed 's/|.*//g') if [ -z "${IP4_IF}" ]; then config_netif - IP4_DEFINITION="ip4.addr = ${NETIF_CONFIG}|${IP4_CONFIG};" + IP4_DEFINITION="ip4.addr = ${NETIF_CONFIG}|${IP4_CONFIG};" IP6_MODE="disable" else IP4_DEFINITION="ip4.addr = ${IP4_CONFIG};" - IP6_MODE="disable" - fi + IP6_MODE="disable" + fi else IP4_IF=$(echo "${IP4_CONFIG}" | grep '.*|' | sed 's/|.*//g') if [ -z "${IP4_IF}" ]; then config_netif - IP4_DEFINITION="ip4.addr = ${NETIF_CONFIG}|${IP4_CONFIG};" + IP4_DEFINITION="ip4.addr = ${NETIF_CONFIG}|${IP4_CONFIG};" IP6_MODE="disable" else IP4_DEFINITION="ip4.addr = ${IP4_CONFIG};" - IP6_MODE="disable" - fi + IP6_MODE="disable" + fi fi - # IP6 set, but not IP4 + # IP6 set, but not IP4 elif [ -z "${IP4_CONFIG}" ] && [ -z "${IP6_CONFIG}" ]; then if ! echo "${IP6_CONFIG}" | grep -q '.*,.*'; then IP6_IF=$(echo "${IP6_CONFIG}" | grep '.*|' | sed 's/|.*//g') if [ -z "${IP6_IF}" ]; then config_netif - IP6_DEFINITION="ip6.addr = ${NETIF_CONFIG}|${IP6_CONFIG};" + IP6_DEFINITION="ip6.addr = ${NETIF_CONFIG}|${IP6_CONFIG};" IP6_MODE="new" else IP6_DEFINITION="ip6.addr = ${IP6_CONFIG};" - IP6_MODE="new" - fi + IP6_MODE="new" + fi else IP6_IF=$(echo "${IP6_CONFIG}" | grep '.*|' | sed 's/|.*//g') if [ -z "${IP6_IF}" ]; then @@ -286,48 +291,48 @@ generate_config() { IP6_MODE="new" else IP6_DEFINITION="ip6.addr = ${IP6_CONFIG};" - IP6_MODE="new" - fi + IP6_MODE="new" + fi fi # IP4 and IP6 both set - elif [ -n "${IP4_CONFIG}" ] && [ -n "${IP6_CONFIG}" ]; then + elif [ -n "${IP4_CONFIG}" ] && [ -n "${IP6_CONFIG}" ]; then if ! echo "${IP4_CONFIG}" | grep -q '.*,.*'; then IP4_IF=$(echo "${IP4_CONFIG}" | grep '.*|' | sed 's/|.*//g') if [ -z "${IP4_IF}" ]; then config_netif - IP4_DEFINITION="ip4.addr = ${NETIF_CONFIG}|${IP4_CONFIG};" + IP4_DEFINITION="ip4.addr = ${NETIF_CONFIG}|${IP4_CONFIG};" else IP4_DEFINITION="ip4.addr = ${IP4_CONFIG};" - fi + fi else IP4_IF=$(echo "${IP4_CONFIG}" | grep '.*|' | sed 's/|.*//g') if [ -z "${IP4_IF}" ]; then config_netif - IP4_DEFINITION="ip4.addr = ${NETIF_CONFIG}|${IP4_CONFIG};" + IP4_DEFINITION="ip4.addr = ${NETIF_CONFIG}|${IP4_CONFIG};" else IP4_DEFINITION="ip4.addr = ${IP4_CONFIG};" - fi + fi fi if ! echo "${IP6_CONFIG}" | grep -q '.*,.*'; then IP6_IF=$(echo "${IP6_CONFIG}" | grep '.*|' | sed 's/|.*//g') if [ -z "${IP6_IF}" ]; then config_netif - IP6_DEFINITION="ip6.addr = ${NETIF_CONFIG}|${IP6_CONFIG};" + IP6_DEFINITION="ip6.addr = ${NETIF_CONFIG}|${IP6_CONFIG};" IP6_MODE="new" else IP6_DEFINITION="ip6.addr = ${IP6_CONFIG};" - IP6_MODE="new" - fi + IP6_MODE="new" + fi else IP6_IF=$(echo "${IP6_CONFIG}" | grep '.*|' | sed 's/|.*//g') if [ -z "${IP6_IF}" ]; then config_netif - IP6_DEFINITION="ip6.addr = ${NETIF_CONFIG}|${IP6_CONFIG};" + IP6_DEFINITION="ip6.addr = ${NETIF_CONFIG}|${IP6_CONFIG};" IP6_MODE="new" - else - IP6_DEFINITION="ip6.addr = ${IP6_CONFIG};" + else + IP6_DEFINITION="ip6.addr = ${IP6_CONFIG};" IP6_MODE="new" - fi + fi fi # ezjail import elif [ -n "${IPVX_CONFIG}" ]; then @@ -335,14 +340,14 @@ generate_config() { NETIF_CONFIG=$(echo "${IPVX_CONFIG}" | grep '.*|' | sed 's/|.*//g') if [ -z "${NETIF_CONFIG}" ]; then config_netif - IP4_DEFINITION="ip4.addr = ${NETIF_CONFIG}|${IPVX_CONFIG};" + IP4_DEFINITION="ip4.addr = ${NETIF_CONFIG}|${IPVX_CONFIG};" IP6_MODE="disable" else IP4_DEFINITION="ip4.addr = ${IPVX_CONFIG};" - IP6_MODE="disable" - fi + IP6_MODE="disable" + fi if echo "${IPVX_CONFIG}" | sed 's/.*|//' | grep -Eq '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$))'; then - IP4_DEFINITION="" + IP4_DEFINITION="" IP6_DEFINITION="ip6.addr = ${IPVX_CONFIG};" IP6_MODE="new" fi @@ -369,7 +374,7 @@ EOF if [ -z "${CONFIG_RELEASE}" ]; then # Fallback to host version CONFIG_RELEASE=$(freebsd-version | sed 's/\-[pP].*//') - warn "Warning: ${CONFIG_RELEASE} was set by default!" + warn "[WARNING]: ${CONFIG_RELEASE} was set by default!" fi mkdir "${bastille_jailsdir}/${TARGET_TRIM}/root/.bastille" echo "${bastille_releasesdir}/${CONFIG_RELEASE} ${bastille_jailsdir}/${TARGET_TRIM}/root/.bastille nullfs ro 0 0" \ @@ -405,6 +410,7 @@ EOF } update_config() { + # Update an existing jail configuration # The config on select archives does not provide a clear way to determine # the base release, so lets try to get it from the base/COPYRIGHT file, @@ -414,11 +420,13 @@ update_config() { else CONFIG_RELEASE="${RELEASE}" fi + if [ -z "${CONFIG_RELEASE}" ]; then # Fallback to host version CONFIG_RELEASE=$(freebsd-version | sed 's/\-[pP].*//') - warn "Warning: ${CONFIG_RELEASE} was set by default!" + warn "[WARNING]: ${CONFIG_RELEASE} was set by default!" fi + mkdir "${bastille_jailsdir}/${TARGET_TRIM}/root/.bastille" echo "${bastille_releasesdir}/${CONFIG_RELEASE} ${bastille_jailsdir}/${TARGET_TRIM}/root/.bastille nullfs ro 0 0" \ >> "${bastille_jailsdir}/${TARGET_TRIM}/fstab" @@ -448,7 +456,7 @@ vnet_requirements() { if [ -f "/usr/share/examples/jails/jib" ] && [ ! -f "/usr/local/bin/jib" ]; then install -m 0544 /usr/share/examples/jails/jib /usr/local/bin/jib else - warn "Warning: Unable to locate/install jib script required by VNET jails." + warn "[WARNING]: Unable to locate/install jib script required by VNET jails." fi fi elif [ "${bastille_network_vnet_type}" = "netgraph" ]; then @@ -456,7 +464,7 @@ vnet_requirements() { if [ -f "/usr/share/examples/jails/jng" ] && [ ! -f "/usr/local/bin/jng" ]; then install -m 0544 /usr/share/examples/jails/jng /usr/local/bin/jng else - warn "Warning: Unable to locate/install jng script required by VNET jails." + warn "[WARNING]: Unable to locate/install jng script required by VNET jails." fi fi fi @@ -474,16 +482,17 @@ config_netif() { } update_symlinks() { + # Work with the symlinks SYMLINKS="bin boot lib libexec rescue sbin usr/bin usr/include usr/lib usr/lib32 usr/libdata usr/libexec usr/ports usr/sbin usr/share usr/src" # Just warn user to bootstrap the release if missing if [ ! -d "${bastille_releasesdir}/${CONFIG_RELEASE}" ]; then - warn "Warning: ${CONFIG_RELEASE} must be bootstrapped. See 'bastille bootstrap'." + warn "[WARNING]: ${CONFIG_RELEASE} must be bootstrapped. See 'bastille bootstrap'." fi # Update old symlinks - info "Updating symlinks..." + info "\nUpdating symlinks..." for _link in ${SYMLINKS}; do if [ -L "${_link}" ]; then ln -sf /.bastille/${_link} ${_link} @@ -492,7 +501,7 @@ update_symlinks() { ln -sfF /.bastille/${_link} ${_link} || EXIT_CODE=$? if [ "${EXIT_CODE:-0}" != "0" ]; then # Assume that the failure was due to the directory not being empty and explain the problem in friendlier terms - warn "Warning: directory ${_link} on imported jail was not empty and will not be updated by Bastille" + warn "[WARNING]: directory ${_link} on imported jail was not empty and will not be updated by Bastille" fi fi done @@ -500,8 +509,8 @@ update_symlinks() { create_zfs_datasets() { # Prepare the ZFS environment and restore from file - info "Importing '${TARGET_TRIM}' from foreign compressed ${FILE_EXT} archive." - info "Preparing ZFS environment..." + info "\nImporting '${TARGET_TRIM}' from foreign compressed ${FILE_EXT} archive." + echo "Preparing ZFS environment..." # Create required ZFS datasets, mountpoint inherited from system zfs create ${bastille_zfs_options} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" @@ -512,7 +521,7 @@ remove_zfs_datasets() { # Perform cleanup on failure zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" - error_exit "Failed to extract files from '${TARGET}' archive." + error_exit "[ERROR]: Failed to extract files from '${TARGET}' archive." } jail_import() { @@ -525,8 +534,8 @@ jail_import() { if [ "${FILE_EXT}" = ".xz" ]; then validate_archive # Import from compressed xz on ZFS systems - info "Importing '${TARGET_TRIM}' from compressed ${FILE_EXT} image." - info "Receiving ZFS data stream..." + info "\nImporting '${TARGET_TRIM}' from compressed ${FILE_EXT} image." + echo "Receiving ZFS data stream..." xz ${bastille_decompress_xz_options} "${bastille_backupsdir}/${TARGET}" | \ zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" @@ -535,8 +544,8 @@ jail_import() { elif [ "${FILE_EXT}" = ".gz" ]; then validate_archive # Import from compressed xz on ZFS systems - info "Importing '${TARGET_TRIM}' from compressed ${FILE_EXT} image." - info "Receiving ZFS data stream..." + info "\nImporting '${TARGET_TRIM}' from compressed ${FILE_EXT} image." + echo "Receiving ZFS data stream..." gzip ${bastille_decompress_gz_options} "${bastille_backupsdir}/${TARGET}" | \ zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" @@ -549,7 +558,7 @@ jail_import() { create_zfs_datasets # Extract required files to the new datasets - info "Extracting files from '${TARGET}' archive..." + info "\nExtracting files from '${TARGET}' archive..." tar --exclude='root' -Jxf "${bastille_backupsdir}/${TARGET}" --strip-components 1 -C "${bastille_jailsdir}/${TARGET_TRIM}" tar -Jxf "${bastille_backupsdir}/${TARGET}" --strip-components 2 -C "${bastille_jailsdir}/${TARGET_TRIM}/root" "${TARGET_TRIM}/root" if [ "$?" -ne 0 ]; then @@ -561,7 +570,7 @@ jail_import() { create_zfs_datasets # Extract required files to the new datasets - info "Extracting files from '${TARGET}' archive..." + info "\nExtracting files from '${TARGET}' archive..." tar --exclude='root' -xf "${bastille_backupsdir}/${TARGET}" --strip-components 1 -C "${bastille_jailsdir}/${TARGET_TRIM}" tar -xf "${bastille_backupsdir}/${TARGET}" --strip-components 2 -C "${bastille_jailsdir}/${TARGET_TRIM}/root" "${TARGET_TRIM}/root" if [ "$?" -ne 0 ]; then @@ -570,7 +579,7 @@ jail_import() { elif [ "${FILE_EXT}" = ".zip" ]; then validate_archive # Attempt to import a foreign/iocage container - info "Importing '${TARGET_TRIM}' from foreign compressed ${FILE_EXT} archive." + info "\nImporting '${TARGET_TRIM}' from foreign compressed ${FILE_EXT} archive." # Sane bastille ZFS options ZFS_OPTIONS=$(echo ${bastille_zfs_options} | sed 's/-o//g') @@ -580,7 +589,7 @@ jail_import() { error_exit "Failed to extract files from '${TARGET}' archive." rm -f "${FILE_TRIM}" "${FILE_TRIM}_root" fi - info "Receiving ZFS data stream..." + echo "Receiving ZFS data stream..." zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" < "${FILE_TRIM}" zfs set ${ZFS_OPTIONS} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" < "${FILE_TRIM}_root" @@ -604,7 +613,7 @@ jail_import() { create_zfs_datasets # Extract required files to the new datasets - info "Extracting files from '${TARGET}' archive..." + info "\nExtracting files from '${TARGET}' archive..." tar --exclude='ezjail/' -xf "${bastille_backupsdir}/${TARGET}" -C "${bastille_jailsdir}/${TARGET_TRIM}" tar -xf "${bastille_backupsdir}/${TARGET}" --strip-components 1 -C "${bastille_jailsdir}/${TARGET_TRIM}/root" if [ "$?" -ne 0 ]; then @@ -619,7 +628,7 @@ jail_import() { workout_components # Extract required files to the new datasets - info "Extracting files from '${TARGET}' archive..." + info "\nExtracting files from '${TARGET}' archive..." tar -xf "${bastille_backupsdir}/${TARGET}" --strip-components "${CONF_TRIM}" -C "${bastille_jailsdir}/${TARGET_TRIM}" "${JAIL_CONF}" tar -xf "${bastille_backupsdir}/${TARGET}" --strip-components "${DIRS_PLUS}" -C "${bastille_jailsdir}/${TARGET_TRIM}/root" "${JAIL_PATH}" if [ -f "${bastille_jailsdir}/${TARGET_TRIM}/${TARGET_TRIM}" ]; then @@ -636,8 +645,8 @@ jail_import() { validate_archive # Based on the file name, looks like we are importing a raw bastille image # Import from uncompressed image file - info "Importing '${TARGET_TRIM}' from uncompressed image archive." - info "Receiving ZFS data stream..." + info "\nImporting '${TARGET_TRIM}' from uncompressed image archive." + echo "Receiving ZFS data stream..." zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" < "${bastille_backupsdir}/${TARGET}" # Update ZFS mountpoint property if required @@ -653,27 +662,27 @@ jail_import() { fi fi else - error_exit "Unknown archive format." + error_exit "[ERROR]: Unknown archive format." fi fi else # Import from standard supported archives on UFS systems if [ "${FILE_EXT}" = ".txz" ]; then - info "Extracting files from '${TARGET}' archive..." + info "\nExtracting files from '${TARGET}' archive..." tar -Jxf "${bastille_backupsdir}/${TARGET}" -C "${bastille_jailsdir}" elif [ "${FILE_EXT}" = ".tgz" ]; then - info "Extracting files from '${TARGET}' archive..." + info "\nExtracting files from '${TARGET}' archive..." tar -xf "${bastille_backupsdir}/${TARGET}" -C "${bastille_jailsdir}" elif [ "${FILE_EXT}" = ".tar.gz" ]; then # Attempt to import/configure foreign/ezjail container - info "Extracting files from '${TARGET}' archive..." + info "\nExtracting files from '${TARGET}' archive..." mkdir "${bastille_jailsdir}/${TARGET_TRIM}" tar -xf "${bastille_backupsdir}/${TARGET}" -C "${bastille_jailsdir}/${TARGET_TRIM}" mv "${bastille_jailsdir}/${TARGET_TRIM}/ezjail" "${bastille_jailsdir}/${TARGET_TRIM}/root" generate_config elif [ "${FILE_EXT}" = ".tar" ]; then # Attempt to import/configure foreign/qjail container - info "Extracting files from '${TARGET}' archive..." + info "\nExtracting files from '${TARGET}' archive..." mkdir -p "${bastille_jailsdir}/${TARGET_TRIM}/root" workout_components tar -xf "${bastille_backupsdir}/${TARGET}" --strip-components "${CONF_TRIM}" -C "${bastille_jailsdir}/${TARGET_TRIM}" "${JAIL_CONF}" @@ -683,24 +692,24 @@ jail_import() { fi update_config else - error_exit "Unsupported archive format." + error_exit "[ERROR]: Unsupported archive format." fi fi if [ "$?" -ne 0 ]; then - error_exit "Failed to import from '${TARGET}' archive." + error_exit "[ERROR]: Failed to import from '${TARGET}' archive." else # Update the jail.conf and fstab if required # This is required on foreign imports only update_jailconf update_fstab_import if [ -z "${USER_IMPORT}" ]; then - info "Container '${TARGET_TRIM}' imported successfully." + info "\nJail: '${TARGET_TRIM}' imported successfully." fi exit 0 fi else - error_exit "Jails directory/dataset does not exist. See 'bastille bootstrap'." + error_exit "[ERROR]: Jails directory/dataset does not exist. See 'bastille bootstrap'." fi } @@ -713,7 +722,7 @@ fi # Check if backups directory/dataset exist if [ ! -d "${bastille_backupsdir}" ]; then - error_exit "Backups directory/dataset does not exist. See 'bastille bootstrap'." + error_exit "[ERROR]: Backups directory/dataset does not exist. See 'bastille bootstrap'." fi # Check if archive exist then trim archive name @@ -724,11 +733,11 @@ if [ -f "${bastille_backupsdir}/${TARGET}" ]; then TARGET_TRIM=$(echo "${TARGET}" | sed "s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.xz//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.gz//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.tgz//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.txz//;s/_[0-9]*-[0-9]*-[0-9]*.zip//;s/-[0-9]\{12\}.[0-9]\{2\}.tar.gz//;s/@[0-9]\{12\}.[0-9]\{2\}.tar//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*//") fi else - error_exit "Unrecognized archive name." + error_exit "[ERROR]: Unrecognized archive name." fi else if echo "${TARGET}" | grep -q '_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.*$'; then - error_exit "Archive '${TARGET}' not found." + error_exit "[ERROR]: Archive '${TARGET}' not found." else # Assume user will import from standard input TARGET_TRIM=${TARGET} @@ -737,16 +746,9 @@ else fi # Check if a running jail matches name or already exist -if [ -n "$(/usr/sbin/jls name | awk "/^${TARGET_TRIM}$/")" ]; then - error_exit "A running jail matches name." -elif [ -n "${TARGET_TRIM}" ]; then - if [ -d "${bastille_jailsdir}/${TARGET_TRIM}" ]; then - error_exit "Container: ${TARGET_TRIM} already exists." - fi -fi +check_target_exists || error_exit "[ERROR]: Jail: ${TARGET_TRIM} already exists." if [ -n "${TARGET}" ]; then + info "\nAttempting to import jail: ${TARGET}..." jail_import -fi - -echo +fi \ No newline at end of file diff --git a/usr/local/share/bastille/jcp.sh b/usr/local/share/bastille/jcp.sh index 3e1789dd..fbc3e829 100644 --- a/usr/local/share/bastille/jcp.sh +++ b/usr/local/share/bastille/jcp.sh @@ -65,7 +65,7 @@ while [ "$#" -gt 0 ]; do case ${_opt} in q) OPTION="-a" ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -95,13 +95,13 @@ for _jail in ${DEST_TARGET}; do continue else - info "\n[${_jail}]:" - - source_path="$(echo ${bastille_jailsdir}/${SOURCE_TARGET}/root/${SOURCE_PATH} | sed 's#//#/#g')" + info "\n[${_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}" + error_continue "[ERROR]: JCP failed: ${source_path} -> ${dest_path}" fi fi diff --git a/usr/local/share/bastille/limits.sh b/usr/local/share/bastille/limits.sh index 39aaa323..a2957f77 100644 --- a/usr/local/share/bastille/limits.sh +++ b/usr/local/share/bastille/limits.sh @@ -51,9 +51,9 @@ EOF AUTO=0 while [ "$#" -gt 0 ]; do case "${1}" in - -h|--help|help) - usage - ;; + -h|--help|help) + usage + ;; -a|--auto) AUTO=1 shift @@ -67,7 +67,7 @@ while [ "$#" -gt 0 ]; do case ${_opt} in a) AUTO=1 ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -95,7 +95,7 @@ fi RACCT_ENABLE="$(sysctl -n kern.racct.enable)" if [ "${RACCT_ENABLE}" != '1' ]; then - error_exit "Racct not enabled. Append 'kern.racct.enable=1' to /boot/loader.conf and reboot" + error_exit "[ERROR]: Racct not enabled. Append 'kern.racct.enable=1' to /boot/loader.conf and reboot" fi bastille_root_check @@ -103,16 +103,15 @@ set_target "${TARGET}" for _jail in ${JAILS}; do - info "\n[${_jail}]:" - check_target_is_running "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-starting ${_jail}..." bastille start "${_jail}" else - info "[${_jail}]:" + info "\n[${_jail}]:" error_notify "Jail is not running." error_continue "Use [-a|--auto] to auto-start the jail." fi + + info "\n[${_jail}]:" case "${ACTION}" in add) @@ -186,11 +185,8 @@ for _jail in ${JAILS}; do rm -f "${bastille_jailsdir}/${_jail}/rctl.conf" echo "rctl.conf removed." else - error_continue "rctl.conf not found." + error_continue "[ERROR]: rctl.conf not found." fi ;; esac - -done - -echo +done \ No newline at end of file diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index 9b968ee5..4757ea86 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -512,7 +512,7 @@ while [ "$#" -gt 0 ]; do a) ;; j) OPT_JSON=1 ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" esac done shift @@ -609,4 +609,4 @@ if [ "$#" -eq 1 ]; then fi ;; esac -fi +fi \ No newline at end of file diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index ab6d41ed..d412a00c 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.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 "[ERROR]: Unknown Option: \"${1}\"" esac done shift @@ -106,7 +106,6 @@ if [ -z "${_hostpath}" ] || [ -z "${_jailpath}" ] || [ -z "${_type}" ] || [ -z " error_notify "FSTAB format not recognized." warn "Format: /host/path /jail/path nullfs ro 0 0" warn "Read: ${_fstab}" - usage fi # Exit if host path doesn't exist, type is not "nullfs", or mount is an advanced mount type "tmpfs,linprocfs,linsysfs,fdescfs,procfs" @@ -122,7 +121,6 @@ elif [ ! -e "${_hostpath}" ] || [ "${_type}" != "nullfs" ]; then error_notify "Invalid host path or incorrect mount type in FSTAB." warn "Format: /host/path /jail/path nullfs ro 0 0" warn "Read: ${_fstab}" - usage fi # Mount permissions,options must include one of "ro, rw, rq, sw, xx" @@ -130,7 +128,6 @@ 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}" - usage fi # Dump and pass need to be "0 0 - 1 1" @@ -138,21 +135,20 @@ if [ "${_checks}" != "0 0" ] && [ "${_checks}" != "1 0" ] && [ "${_checks}" != " error_notify "Detected invalid fstab options in FSTAB." warn "Format: /host/path /jail/path nullfs ro 0 0" warn "Read: ${_fstab}" - usage fi for _jail in ${JAILS}; do - info "\n[${_jail}]:" - check_target_is_running "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-starting ${_jail}..." bastille start "${_jail}" else + info "\n[${_jail}]:" error_notify "Jail is not running." error_continue "Use [-a|--auto] to auto-start the jail." fi - + + info "\n[${_jail}]:" + _fullpath_fstab="$( echo "${bastille_jailsdir}/${_jail}/root/${_jailpath_fstab}" 2>/dev/null | sed 's#//#/#' )" _fullpath="$( echo "${bastille_jailsdir}/${_jail}/root/${_jailpath}" 2>/dev/null | sed 's#//#/#' )" _fstab_entry="${_hostpath_fstab} ${_fullpath_fstab} ${_type} ${_perms} ${_checks}" @@ -199,7 +195,5 @@ for _jail in ${JAILS}; do echo "${_fstab_entry}" >> "${bastille_jailsdir}/${_jail}/fstab" || error_continue "Failed to create fstab entry: ${_fstab_entry}" mount -F "${bastille_jailsdir}/${_jail}/fstab" -a || error_continue "Failed to mount volume: ${_fullpath}" echo "Added: ${_fstab_entry}" - -done -echo \ No newline at end of file +done \ No newline at end of file diff --git a/usr/local/share/bastille/network.sh b/usr/local/share/bastille/network.sh index 411e8d75..4040cf41 100644 --- a/usr/local/share/bastille/network.sh +++ b/usr/local/share/bastille/network.sh @@ -118,7 +118,7 @@ while [ "$#" -gt 0 ]; do P) PASSTHROUGH=1 ;; V) VNET=1 ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -135,7 +135,7 @@ INTERFACE="${3}" if [ "${ACTION}" = "add" ] && [ "${NO_IP}" -eq 0 ] && [ -n "${4}" ]; then IP="${4}" elif [ "${NO_IP}" -eq 1 ] && [ -n "${4}" ]; then - error_notify "IP should not be present when using -n|--no-ip." + error_exit "[ERROR]: IP should not be present when using -n|--no-ip." else IP="" fi @@ -147,15 +147,15 @@ if [ "${ACTION}" = "add" ]; then { [ "${BRIDGE}" -eq 1 ] && [ "${CLASSIC}" -eq 1 ]; } || \ { [ "${BRIDGE}" -eq 1 ] && [ "${PASSTHROUGH}" -eq 1 ]; } || \ { [ "${CLASSIC}" -eq 1 ] && [ "${PASSTHROUGH}" -eq 1 ]; } then - error_notify "Error: Only one of [-B|--bridge], [-C|--classic], [-P|--passthrough] or [-V|--vnet] should be set." + error_exit "[ERROR]: Only one of [-B|--bridge], [-C|--classic], [-P|--passthrough] or [-V|--vnet] should be set." elif [ "${VNET}" -eq 0 ] && [ "${BRIDGE}" -eq 0 ] && [ "${CLASSIC}" -eq 0 ] && [ "${PASSTHROUGH}" -eq 0 ]; then - error_notify "Error: [-B|--bridge], [-C|--classic], [-P|--passthrough] or [-V|--vnet] must be set." + error_exit "[ERROR]: [-B|--bridge], [-C|--classic], [-P|--passthrough] or [-V|--vnet] must be set." elif [ "${VNET}" -eq 0 ] && [ "${BRIDGE}" -eq 0 ] && [ "${PASSTHROUGH}" -eq 0 ] && [ -n "${VLAN_ID}" ]; then - error_notify "VLANs can only be used with VNET interfaces." + error_exit "[ERROR]: VLANs can only be used with VNET interfaces." elif [ "${VNET}" -eq 0 ] && [ "${BRIDGE}" -eq 0 ] && [ "${NO_IP}" -eq 1 ]; then - error_notify "[-n|--no-ip] can only be used with VNET jails." + error_exit "[ERROR]: [-n|--no-ip] can only be used with VNET jails." elif [ "${bastille_network_vnet_type}" = "netgraph" ] && [ "${BRIDGE}" -eq 1 ]; then - error_notify "[-B|--bridge] cannot be used with Netgraph." + error_exit "[ERROR]: [-B|--bridge] cannot be used with Netgraph." fi fi @@ -166,23 +166,26 @@ fi bastille_root_check set_target_single "${TARGET}" +# Validate jail state check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-stopping ${TARGET}..." bastille stop "${TARGET}" -else +else + info "\n[${_jail}]:" error_notify "Jail is running." error_exit "Use [-a|--auto] to auto-stop the jail." fi validate_ip() { + IP6_ENABLE=0 local ip="${1}" local ip6="$( echo "${ip}" 2>/dev/null | grep -E '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$)|SLAAC)' )" + if [ -n "${ip6}" ]; then - info "Valid: (${ip6})." + info "\nValid: (${ip6})." IP6_ENABLE=1 elif [ "${ip}" = "0.0.0.0" ] || [ "${ip}" = "DHCP" ]; then - info "Valid: (${ip})." + info "\nValid: (${ip})." else local IFS if echo "${ip}" 2>/dev/null | grep -Eq '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))?$'; then @@ -194,7 +197,7 @@ validate_ip() { error_exit "Invalid: (${TEST_IP})" fi done - info "Valid: (${ip})." + info "\nValid: (${ip})." else error_exit "Invalid: (${ip})." fi @@ -202,18 +205,22 @@ validate_ip() { } validate_netif() { + local _interface="${1}" + if ifconfig -l | grep -qwo ${_interface}; then - info "Valid: (${_interface})." + info "\nValid: (${_interface})." else error_exit "Invalid: (${_interface})." fi } check_interface_added() { + local _jailname="${1}" local _if="${2}" local _jail_config="${bastille_jailsdir}/${_jailname}/jail.conf" + if grep -qo "${_if}" "${_jail_config}"; then return 0 else @@ -222,6 +229,7 @@ check_interface_added() { } add_interface() { + local _jailname="${1}" local _if="${2}" local _ip="${3}" @@ -232,6 +240,7 @@ add_interface() { local _vnet_if_count="$(grep -Eo 'vnet[1-9]+' ${_jail_rc_config} | sort -u | wc -l | awk '{print $1}')" local _if_vnet="vnet$((_vnet_if_count + 1))" local _bastille_if_num_range=$((_bastille_if_count + 1)) + if [ "${BRIDGE}" -eq 1 ]; then if [ "${_bastille_if_count}" -gt 0 ]; then for _num in $(seq 0 "${_bastille_if_num_range}"); do @@ -426,9 +435,11 @@ EOF } remove_interface() { + local _jailname="${1}" local _if="${2}" local _jail_config="${bastille_jailsdir}/${_jailname}/jail.conf" + # Skip next block in case of classic jail if [ "$(bastille config ${TARGET} get vnet)" != "not set" ]; then local _jail_rc_config="${bastille_jailsdir}/${_jailname}/root/etc/rc.conf" @@ -452,31 +463,31 @@ remove_interface() { local _if_jail="${_if}" _if_type="passthrough" else - error_exit "Could not find interface inside jail: \"${_if_jail}\"" + error_exit "[ERROR]: Could not find interface inside jail: \"${_if_jail}\"" fi if [ "${_if_type}" = "bastille" ] || [ "${_if_type}" = "epair" ]; then if grep -oq "${_if_jail}" ${_jail_config}; then local _if_vnet="$(grep ${_if_jail} ${_jail_rc_config} | grep -Eo 'vnet[0-9]+')" else - error_exit "Interface not found: ${_if_jail}" + error_exit "[ERROR]: Interface not found: ${_if_jail}" fi elif [ "${_if_type}" = "passthrough" ]; then if grep -oq "${_if_jail}" ${_jail_config}; then local _if_vnet="${_if_jail}" else - error_exit "Interface not found: ${_if_jail}" + error_exit "[ERROR]: Interface not found: ${_if_jail}" fi fi # Do not allow removing default vnet0 interface if [ "${_if_vnet}" = "vnet0" ]; then - error_exit "Default interface cannot be removed." + error_exit "[ERROR]: Default interface cannot be removed." fi # Avoid removing entire file contents if variables aren't set for some reason if [ -z "${_if_jail}" ]; then - error_exit "Error: Could not find specifed interface." + error_exit "[ERROR]: Could not find specifed interface." fi # Remove interface from /etc/rc.conf @@ -484,13 +495,13 @@ remove_interface() { if [ -n "${_if_vnet}" ] && echo ${_if_vnet} 2>/dev/null | grep -Eoq 'vnet[0-9]+'; then sed -i '' "/.*${_if_vnet}.*/d" "${_jail_rc_config}" else - error_exit "Failed to remove interface from /etc/rc.conf" + error_exit "[ERROR]: Failed to remove interface from /etc/rc.conf" fi elif [ "${_if_type}" = "passthrough" ]; then if [ -n "${_if_vnet}" ]; then sed -i '' "/.*${_if_vnet}.*/d" "${_jail_rc_config}" else - error_exit "Failed to remove interface from /etc/rc.conf" + error_exit "[ERROR]: Failed to remove interface from /etc/rc.conf" fi fi @@ -507,18 +518,18 @@ remove_interface() { sed -i '' "/.*${_if_jail}.*/d" "${_jail_config}" fi else - error_exit "Failed to remove interface from jail.conf" + error_exit "[ERROR]: Failed to remove interface from jail.conf" fi else # Remove interface from jail.conf (non-VNET) if [ -n "${_if}" ]; then if grep ${_if} ${_jail_config} 2>/dev/null | grep -qo " = "; then - error_exit "Default interface cannot be removed." + error_exit "[ERROR]: Default interface cannot be removed." else sed -i '' "/.*${_if}.*/d" "${_jail_config}" fi else - error_exit "Failed to remove interface from jail.conf" + error_exit "[ERROR]: Failed to remove interface from jail.conf" fi fi @@ -526,12 +537,14 @@ remove_interface() { } add_vlan() { + local _jailname="${1}" local _interface="${2}" local _ip="${3}" local _vlan_id="${4}" local _jail_config="${bastille_jailsdir}/${_jailname}/jail.conf" local _jail_rc_config="${bastille_jailsdir}/${_jailname}/root/etc/rc.conf" + if [ "${VNET}" -eq 1 ]; then local _jail_epair_num="$(grep ${_interface} ${_jail_config} | grep -Eo -m 1 "bastille[0-9]+" | grep -Eo "[0-9]+")" local _jail_vnet="$(grep "e0b_bastille${_jail_epair_num}_name" ${_jail_rc_config} | grep -Eo "vnet[0-9]+")" @@ -542,7 +555,7 @@ add_vlan() { local _jail_vnet="${_interface}" fi if grep -Eq "ifconfig_${_jail_vnet}_${_vlan_id}" "${bastille_jailsdir}/${_jailname}/root/etc/rc.conf"; then - error_exit "VLAN has already been added: VLAN ${_vlan_id}" + error_exit "[ERROR]: VLAN has already been added: VLAN ${_vlan_id}" else bastille start "${_jailname}" bastille template "${_jailname}" ${bastille_template_vlan} --arg VLANID="${_vlan_id}" --arg IFCONFIG="inet ${_ip}" --arg JAIL_VNET="${_jail_vnet}" @@ -571,9 +584,9 @@ case "${ACTION}" in fi if [ "${VNET}" -eq 1 ]; then if [ "$(bastille config ${TARGET} get vnet)" = "not set" ]; then - error_exit "Error: ${TARGET} is not a VNET jail." + error_exit "[ERROR]: ${TARGET} is not a VNET jail." elif ifconfig -g bridge | grep -owq "${INTERFACE}"; then - error_exit "\"${INTERFACE}\" is a bridge interface." + error_exit "[ERROR]: '${INTERFACE}' is a bridge interface." else add_interface "${TARGET}" "${INTERFACE}" "${IP}" if [ -n "${VLAN_ID}" ]; then @@ -585,13 +598,13 @@ case "${ACTION}" in fi elif [ "${BRIDGE}" -eq 1 ]; then if [ "$(bastille config ${TARGET} get vnet)" = "not set" ]; then - error_exit "Error: ${TARGET} is not a VNET jail." + error_exit "[ERROR]: ${TARGET} is not a VNET jail." elif ! ifconfig -g bridge | grep -owq "${INTERFACE}"; then - error_exit "\"${INTERFACE}\" is not a bridge interface." + error_exit "[ERROR]: '${INTERFACE}' is not a bridge interface." else add_interface "${TARGET}" "${INTERFACE}" "${IP}" - if [ -n "${VLAN_ID}" ]; then - add_vlan "${TARGET}" "${INTERFACE}" "${IP}" "${VLAN_ID}" + if [ -n "${VLAN_ID}" ]; then + add_vlan "${TARGET}" "${INTERFACE}" "${IP}" "${VLAN_ID}" fi if [ "${AUTO}" -eq 1 ]; then bastille start "${TARGET}" @@ -599,7 +612,7 @@ case "${ACTION}" in fi elif [ "${PASSTHROUGH}" -eq 1 ]; then if [ "$(bastille config ${TARGET} get vnet)" = "not set" ]; then - error_exit "Error: ${TARGET} is not a VNET jail." + error_exit "[ERROR]: ${TARGET} is not a VNET jail." else add_interface "${TARGET}" "${INTERFACE}" "${IP}" fi @@ -611,7 +624,7 @@ case "${ACTION}" in fi elif [ "${CLASSIC}" -eq 1 ]; then if [ "$(bastille config ${TARGET} get vnet)" != "not set" ]; then - error_exit "Error: ${TARGET} is a VNET jail." + error_exit "[ERROR]: ${TARGET} is a VNET jail." else add_interface "${TARGET}" "${INTERFACE}" "${IP}" if [ "${AUTO}" -eq 1 ]; then @@ -624,7 +637,7 @@ case "${ACTION}" in check_interface_added "${TARGET}" "${INTERFACE}" || error_exit "Interface not found in jail.conf: \"${INTERFACE}\"" validate_netif "${INTERFACE}" if ! grep -q "${INTERFACE}" ${bastille_jailsdir}/${TARGET}/jail.conf; then - error_exit "Interface not found in jail.conf: \"${INTERFACE}\"" + error_exit "[ERROR]: Interface not found in jail.conf: \"${INTERFACE}\"" else remove_interface "${TARGET}" "${INTERFACE}" if [ "${AUTO}" -eq 1 ]; then @@ -633,6 +646,6 @@ case "${ACTION}" in fi ;; *) - error_exit "Only [add|remove] are supported." + error_exit "[ERROR]: Only [add|remove] are supported." ;; -esac +esac \ No newline at end of file diff --git a/usr/local/share/bastille/pkg.sh b/usr/local/share/bastille/pkg.sh index 7c0f8980..b6918c8c 100644 --- a/usr/local/share/bastille/pkg.sh +++ b/usr/local/share/bastille/pkg.sh @@ -72,7 +72,7 @@ while [ "$#" -gt 0 ]; do a) AUTO=1 ;; H) USE_HOST_PKG=1 ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -97,17 +97,19 @@ errors=0 for _jail in ${JAILS}; do - info "\n[${_jail}]:" - + # Validate jail state check_target_is_running "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-starting ${_jail}..." bastille start "${_jail}" - else + else + info "\n[${_jail}]:" error_notify "Jail is not running." - error_continue_next_jail "Use [-a|--auto] to auto-start the jail." + error_continue "Use [-a|--auto] to auto-start the jail." fi + info "\n[${_jail}]:" + bastille_jail_path="${bastille_jailsdir}/${_jail}/root" + if [ -f "/usr/sbin/mport" ]; then if ! jexec -l -U root "${_jail}" /usr/sbin/mport "$@"; then errors=1 @@ -129,7 +131,7 @@ for _jail in ${JAILS}; do done if [ $errors -ne 0 ]; then - error_exit "Failed to apply on some jails, please check logs" -fi - -echo + error_exit "[ERROR]: Failed to apply on some jails, please check logs" +else + echo +fi \ No newline at end of file diff --git a/usr/local/share/bastille/rcp.sh b/usr/local/share/bastille/rcp.sh index 2adbcce8..aab2c28b 100644 --- a/usr/local/share/bastille/rcp.sh +++ b/usr/local/share/bastille/rcp.sh @@ -65,7 +65,7 @@ while [ "$#" -gt 0 ]; do case ${_opt} in q) OPTION="-a" ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -93,5 +93,7 @@ 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 + error_exit "[ERROR]: RCP failed: ${jail_path} -> ${host_path}" +else + echo +fi \ No newline at end of file diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 670b0870..24837694 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -49,10 +49,13 @@ EOF } check_jail_validity() { + # Validate jail network type and set IP4/6 if [ "$( bastille config ${TARGET} get vnet )" != 'enabled' ]; then + _ip4_interfaces="$(bastille config ${TARGET} get ip4.addr | sed 's/,/ /g')" _ip6_interfaces="$(bastille config ${TARGET} get ip6.addr | sed 's/,/ /g')" + # Check if jail ip4.addr is valid (non-VNET only) if [ "${_ip4_interfaces}" != "not set" ] && [ "${_ip4_interfaces}" != "disable" ]; then if echo "${_ip4_interfaces}" | grep -q "|"; then @@ -61,6 +64,7 @@ check_jail_validity() { JAIL_IP="$(echo ${_ip4_interfaces} | sed -E 's#/[0-9]+$##g')" fi fi + # Check if jail ip6.addr is valid (non-VNET only) if [ "${_ip6_interfaces}" != "not set" ] && [ "${_ip6_interfaces}" != "disable" ]; then if echo "${_ip6_interfaces}" | grep -q "|"; then @@ -70,20 +74,22 @@ check_jail_validity() { fi fi else - error_exit "VNET jails do not support rdr." + error_exit "[ERROR]: VNET jails do not support rdr." fi # Check if rdr-anchor is defined in pf.conf if ! (pfctl -sn | grep rdr-anchor | grep 'rdr/\*' >/dev/null); then - error_exit "rdr-anchor not found in pf.conf" + error_exit "[ERROR]: rdr-anchor not found in pf.conf" fi } check_rdr_ip_validity() { + local ip="${1}" local ip6="$( echo "${ip}" | grep -E '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$)|SLAAC)' )" + if [ -n "${ip6}" ]; then - info "Valid: (${ip6})." + info "\nValid: (${ip6})." else local IFS if echo "${ip}" | grep -Eq '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))?$'; then @@ -95,7 +101,7 @@ check_rdr_ip_validity() { error_exit "Invalid: (${TEST_IP})" fi done - info "Valid: (${ip})." + info "\nValid: (${ip})." else error_exit "Invalid: (${ip})." fi @@ -103,19 +109,22 @@ check_rdr_ip_validity() { } validate_rdr_rule() { + local if="${1}" local src="${2}" local dst="${3}" local proto="${4}" local host_port="${5}" local jail_port="${6}" + if grep -qs "$if $src $dst $proto $host_port $jail_port" "${bastille_jailsdir}/${TARGET}/rdr.conf"; then - error_notify "Error: Ports already in use on this interface." + error_notify "[ERROR]: Ports already in use on this interface." error_exit "See 'bastille list ports' or 'bastille rdr TARGET reset'." fi } persist_rdr_rule() { + local inet="${1}" local if="${2}" local src="${3}" @@ -123,12 +132,14 @@ persist_rdr_rule() { local proto="${5}" local host_port="${6}" local jail_port="${7}" + if ! grep -qs "$inet $if $src $dst $proto $host_port $jail_port" "${bastille_jailsdir}/${TARGET}/rdr.conf"; then echo "$inet $if $src $dst $proto $host_port $jail_port" >> "${bastille_jailsdir}/${TARGET}/rdr.conf" fi } persist_rdr_log_rule() { + local inet="${1}" local if="${2}" local src="${3}" @@ -138,12 +149,14 @@ persist_rdr_log_rule() { local jail_port="${7}" shift 7; log=$@; + if ! grep -qs "$inet $if $src $dst $proto $host_port $jail_port $log" "${bastille_jailsdir}/${TARGET}/rdr.conf"; then echo "$inet $if $src $dst $proto $host_port $jail_port $log" >> "${bastille_jailsdir}/${TARGET}/rdr.conf" fi } load_rdr_rule() { + local inet="${1}" local if_name="${2}" local if=ext_if=\"${2}\" @@ -152,13 +165,14 @@ load_rdr_rule() { local proto="${5}" local host_port="${6}" local jail_port="${7}" + # Create IPv4 rdr rule # shellcheck disable=SC2193 if { [ "${inet}" = "ipv4" ] || [ "${inet}" = "dual" ]; } then if ! ( pfctl -a "rdr/${TARGET}" -Psn 2>/dev/null; printf '%s\nrdr pass on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ | pfctl -a "rdr/${TARGET}" -f-; then - error_exit "Failed to create IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + error_exit "[ERROR]: Failed to create IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else echo "IPv4 ${proto}/${host_port}:${jail_port} on ${if_name}" fi @@ -169,7 +183,7 @@ load_rdr_rule() { if ! ( pfctl -a "rdr/${TARGET}" -Psn; printf '%s\nrdr pass on $%s inet6 proto %s from %s to %s port %s -> %s port %s\n' "$if" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${TARGET}" -f-; then - error_exit "Failed to create IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + error_exit "[ERROR]: Failed to create IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else echo "IPv6 ${proto}/${host_port}:${jail_port} on ${if_name}" fi @@ -177,6 +191,7 @@ load_rdr_rule() { } load_rdr_log_rule() { + local inet="${1}" local if_name="${2}" local if=ext_if=\"${2}\" @@ -187,24 +202,26 @@ load_rdr_log_rule() { local jail_port="${7}" shift 7; log=$@ + # Create IPv4 rule with log # shellcheck disable=SC2193 if { [ "${inet}" = "ipv4" ] || [ "${inet}" = "dual" ]; } then if ! ( pfctl -a "rdr/${TARGET}" -Psn; printf '%s\nrdr pass %s on $%s inet proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP" "$jail_port" ) \ | pfctl -a "rdr/${TARGET}" -f-; then - error_exit "Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + error_exit "[ERROR]: Failed to create logged IPv4 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else echo "IPv4 ${proto}/${host_port}:${jail_port} on ${if_name}" fi fi + # Create IPv6 rdr rule with log (if ip6.addr is enabled) # shellcheck disable=SC2193 if [ -n "${JAIL_IP6}" ] && { [ "${inet}" = "ipv6" ] || [ "${inet}" = "dual" ]; } then if ! ( pfctl -a "rdr/${TARGET}" -Psn; printf '%s\nrdr pass %s on $%s inet6 proto %s from %s to %s port %s -> %s port %s\n' "$if" "$log" "${bastille_network_pf_ext_if}" "$proto" "$src" "$dst" "$host_port" "$JAIL_IP6" "$jail_port" ) \ | pfctl -a "rdr/${TARGET}" -f-; then - error_exit "Failed to create logged IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" + error_exit "[ERROR]: Failed to create logged IPv6 rdr rule \"${if_name} ${src} ${dst} ${proto} ${host_port} ${jail_port}\"" else echo "IPv6 ${proto}/${host_port}:${jail_port} on ${if_name}" fi @@ -231,7 +248,7 @@ while [ "$#" -gt 0 ]; do RDR_DST="${2}" shift 2 else - error_exit "${2} is not an IP on this system." + error_exit "[ERROR]: '${2}' is not an IP on this system." fi ;; -i|--interface) @@ -240,7 +257,7 @@ while [ "$#" -gt 0 ]; do RDR_IF="${2}" shift 2 else - error_exit "${2} is not a valid interface." + error_exit "[ERROR]: '${2}' is not a valid interface." fi ;; -s|--source) @@ -251,7 +268,7 @@ while [ "$#" -gt 0 ]; do ;; -t|--type) if [ "${2}" != "ipv4" ] && [ "${2}" != "ipv6" ]; then - error_exit "[-t|--type] must be [ipv4|ipv6]" + error_exit "[ERROR]: [-t|--type] must be [ipv4|ipv6]" else OPTION_INET_TYPE=1 RDR_INET="${2}" @@ -263,7 +280,7 @@ while [ "$#" -gt 0 ]; do shift ;; -*) - error_exit "Unknown option: \"${1}\"" + error_exit "[ERROR]: Unknown option: \"${1}\"" ;; *) break @@ -283,13 +300,11 @@ shift bastille_root_check set_target_single "${TARGET}" -info "\n[${TARGET}]:" - while [ "$#" -gt 0 ]; do case "${1}" in list) if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ];then - error_exit "Command \"${1}\" cannot be used with options." + error_exit "[ERROR]: Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage else @@ -300,28 +315,26 @@ while [ "$#" -gt 0 ]; do ;; clear) if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ];then - error_exit "Command \"${1}\" cannot be used with options." + error_exit "[ERROR]: Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage else check_jail_validity - echo "${TARGET} redirects:" pfctl -a "rdr/${TARGET}" -Fn fi shift ;; reset) if [ "${OPTION_IF}" -eq 1 ] || [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] || [ "${OPTION_INET_TYPE}" -eq 1 ];then - error_exit "Command \"${1}\" cannot be used with options." + error_exit "[ERROR]: Command \"${1}\" cannot be used with options." elif [ -n "${2}" ]; then usage else check_jail_validity - echo "${TARGET} redirects:" pfctl -a "rdr/${TARGET}" -Fn - if rm -f "${bastille_jailsdir}/${TARGET}/rdr.conf"; then + if rm -f "${bastille_jailsdir}/${TARGET}/rdr.conf"; then echo "rdr.conf removed" - fi + fi fi shift ;; @@ -329,7 +342,7 @@ while [ "$#" -gt 0 ]; do if [ "$#" -lt 3 ]; then usage elif [ "${OPTION_SRC}" -eq 1 ] || [ "${OPTION_DST}" -eq 1 ] && [ "${OPTION_INET_TYPE}" -ne 1 ];then - error_exit "[-t|--type] must be set when using [-s|--source] or [-d|--destination]" + error_exit "[ERROR]: [-t|--type] must be set when using [-s|--source] or [-d|--destination]" elif [ "$#" -eq 3 ]; then check_jail_validity validate_rdr_rule $RDR_IF $RDR_SRC $RDR_DST $1 $2 $3 @@ -401,6 +414,4 @@ while [ "$#" -gt 0 ]; do fi ;; esac -done - -echo +done \ No newline at end of file diff --git a/usr/local/share/bastille/rename.sh b/usr/local/share/bastille/rename.sh index d28914df..5c462ad5 100644 --- a/usr/local/share/bastille/rename.sh +++ b/usr/local/share/bastille/rename.sh @@ -79,28 +79,33 @@ NEWNAME="${2}" bastille_root_check set_target_single "${TARGET}" +# Validate jail state check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-stopping ${TARGET}..." bastille stop "${TARGET}" -else +else + info "\n[${TARGET}]:" error_notify "Jail is running." error_exit "Use [-a|--auto] to auto-stop the jail." fi validate_name() { + 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!" + error_exit "[ERROR]: Jail names may not begin with (-|_) characters!" elif [ "${NAME_VERIFY}" != "${NAME_SANITY}" ]; then - error_exit "Container names may not contain special characters!" + error_exit "[ERROR]: Jail names may not contain special characters!" fi } update_jailconf() { + # Update jail.conf 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}" @@ -130,6 +135,7 @@ update_jailconf_vnet() { 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 @@ -139,6 +145,7 @@ update_jailconf_vnet() { 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}" @@ -147,18 +154,22 @@ update_jailconf_vnet() { 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 @@ -166,8 +177,8 @@ update_jailconf_vnet() { } change_name() { + # Attempt container name change - info "Attempting to rename '${TARGET}' to ${NEWNAME}..." if checkyesno bastille_zfs_enable; then if [ -n "${bastille_zfs_zpool}" ] && [ -n "${bastille_zfs_prefix}" ]; then # Check and rename container ZFS dataset accordingly @@ -191,10 +202,10 @@ change_name() { ZFS_DATASET_TARGET=$(echo "${ZFS_DATASET_ORIGIN}" | sed "s|\/${TARGET}||") if [ -n "${ZFS_DATASET_ORIGIN}" ] && [ -n "${ZFS_DATASET_TARGET}" ]; then if ! zfs rename -f "${ZFS_DATASET_ORIGIN}" "${ZFS_DATASET_TARGET}/${NEWNAME}"; then - error_exit "Can't rename '${TARGET}' dataset." + error_exit "[ERROR]: Can't rename '${TARGET}' dataset." fi else - error_exit "Can't determine the ZFS origin path of '${TARGET}'." + error_exit "[ERROR]: Can't determine the ZFS origin path of '${TARGET}'." fi else # Just rename the jail directory @@ -208,9 +219,9 @@ change_name() { # Check exit status and notify if [ "$?" -ne 0 ]; then - error_exit "An error has occurred while attempting to rename '${TARGET}'." + error_exit "[ERROR]: An error has occurred while attempting to rename '${TARGET}'." else - info "Renamed '${TARGET}' to '${NEWNAME}' successfully." + echo "Renamed '${TARGET}' to '${NEWNAME}' successfully." if [ "${AUTO}" -eq 1 ]; then bastille start "${NEWNAME}" fi @@ -224,9 +235,11 @@ fi # Check if a jail already exists with NEW_NAME if [ -d "${bastille_jailsdir}/${NEWNAME}" ]; then - error_exit "Jail: ${NEWNAME} already exists." + error_exit "[ERROR]: Jail: ${NEWNAME} already exists." fi +info "\nAttempting to rename '${TARGET}' to ${NEWNAME}..." + change_name -echo \ No newline at end of file +info "\nRenamed '${TARGET}' to '${NEWNAME}' successfully.\n" \ No newline at end of file diff --git a/usr/local/share/bastille/restart.sh b/usr/local/share/bastille/restart.sh index 3b608c45..a812b440 100644 --- a/usr/local/share/bastille/restart.sh +++ b/usr/local/share/bastille/restart.sh @@ -89,7 +89,7 @@ while [ "$#" -gt 0 ]; do _stop_options="${_stop_options} -x" ;; *) - error_exit "Unknown Option: \"${1}\"" + error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done @@ -118,4 +118,4 @@ for _jail in ${JAILS}; do bastille start ${_start_options} ${_jail} fi -done +done \ No newline at end of file diff --git a/usr/local/share/bastille/service.sh b/usr/local/share/bastille/service.sh index 3002d7c0..710b12f1 100644 --- a/usr/local/share/bastille/service.sh +++ b/usr/local/share/bastille/service.sh @@ -49,7 +49,7 @@ EOF AUTO=0 while [ "$#" -gt 0 ]; do case "${1}" in - -h|--help|help) + -h|--help|help) usage ;; -a|--auto) @@ -65,7 +65,7 @@ while [ "$#" -gt 0 ]; do case ${_opt} in a) AUTO=1 ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -88,18 +88,17 @@ set_target "${TARGET}" for _jail in ${JAILS}; do - info "\n[${_jail}]:" - + # Validate jail state check_target_is_running "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-starting ${_jail}..." bastille start "${_jail}" - else + else + info "\n[${_jail}]:" error_notify "Jail is not running." - error_continue_next_jail "Use [-a|--auto] to auto-start the jail." + error_continue "Use [-a|--auto] to auto-start the jail." fi + + info "\n[${_jail}]:" jexec -l "${_jail}" /usr/sbin/service "$@" -done - -echo +done \ No newline at end of file diff --git a/usr/local/share/bastille/setup.sh b/usr/local/share/bastille/setup.sh index 25ddfe0e..a48c3879 100644 --- a/usr/local/share/bastille/setup.sh +++ b/usr/local/share/bastille/setup.sh @@ -250,7 +250,7 @@ case "$1" in configure_pf ;; -n|netgraph) - warn "[WARNING] Bastille only allows using either 'if_bridge' or 'netgraph'" + warn "[WARNING]: Bastille only allows using either 'if_bridge' or 'netgraph'" warn "as VNET network options. You CANNOT use both on the same system. If you have" warn "already started using bastille with 'if_bridge' do not continue." # shellcheck disable=SC3045 @@ -270,7 +270,7 @@ case "$1" in ;; -l|loopback) - warn "[WARNING] Bastille only allows using either the 'loopback' or 'shared'" + warn "[WARNING]: Bastille only allows using either the 'loopback' or 'shared'" warn "interface to be configured ant one time. If you continue, the 'shared'" warn "interface will be disabled, and the 'loopback' interface will be used as default." # shellcheck disable=SC3045 @@ -288,7 +288,7 @@ case "$1" in esac ;; -s|shared) - warn "[WARNING] Bastille only allows using either the 'loopback' or 'shared'" + warn "[WARNING]: Bastille only allows using either the 'loopback' or 'shared'" warn "interface to be configured at one time. If you continue, the 'loopback'" warn "interface will be disabled, and the shared interface will be used as default." # shellcheck disable=SC3045 @@ -315,4 +315,7 @@ case "$1" in configure_vnet configure_bridge ;; + *) + error_exit "[ERROR]: Unknown option: \"${1}\"" + ;; esac \ No newline at end of file diff --git a/usr/local/share/bastille/start.sh b/usr/local/share/bastille/start.sh index 2d534969..995b936a 100644 --- a/usr/local/share/bastille/start.sh +++ b/usr/local/share/bastille/start.sh @@ -82,7 +82,7 @@ while [ "$#" -gt 0 ]; do b) BOOT=1 ;; v) OPTION="-v" ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -134,14 +134,14 @@ for _jail in ${JAILS}; do fi if ifconfig | grep "^${_if}:" >/dev/null; then if ifconfig | grep -qwF "${_ip}"; then - warn "Warning: IP address (${_ip}) already in use, continuing..." + warn "[WARNING]: IP address (${_ip}) already in use, continuing..." fi ## add ip to firewall table if it is not reachable through local interface (assumes NAT/rdr is needed) if route -n get ${_ip} | grep "gateway" >/dev/null; then pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" fi else - error_continue "Error: ${_if} interface does not exist." + error_continue "[ERROR]: ${_if} interface does not exist." fi done fi @@ -157,14 +157,14 @@ for _jail in ${JAILS}; do fi if ifconfig | grep "^${_if}:" >/dev/null; then if ifconfig | grep -qwF "${_ip}"; then - warn "Warning: IP address (${_ip}) already in use, continuing..." + warn "[WARNING]: IP address (${_ip}) already in use, continuing..." fi ## add ip to firewall table if it is not reachable through local interface (assumes NAT/rdr is needed) if route -n get ${_ip} | grep "gateway" >/dev/null; then pfctl -q -t "${bastille_network_pf_table}" -T add "${_ip}" fi else - error_continue "Error: ${_if} interface does not exist." + error_continue "[ERROR]: ${_if} interface does not exist." fi done fi @@ -190,6 +190,4 @@ for _jail in ${JAILS}; do # Delay between jail action sleep "${DELAY_TIME}" -done - -echo +done \ No newline at end of file diff --git a/usr/local/share/bastille/stop.sh b/usr/local/share/bastille/stop.sh index bee06b58..72d696e1 100644 --- a/usr/local/share/bastille/stop.sh +++ b/usr/local/share/bastille/stop.sh @@ -65,7 +65,7 @@ while [ "$#" -gt 0 ]; do case ${_opt} in v) OPTION="-v" ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -136,6 +136,4 @@ for _jail in ${JAILS}; do done fi -done - -echo \ No newline at end of file +done \ No newline at end of file diff --git a/usr/local/share/bastille/sysrc.sh b/usr/local/share/bastille/sysrc.sh index aa4df26d..727080b6 100644 --- a/usr/local/share/bastille/sysrc.sh +++ b/usr/local/share/bastille/sysrc.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 "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -88,16 +88,17 @@ set_target "${TARGET}" for _jail in ${JAILS}; do - info "\n[${_jail}]:" - + # Validate jail state check_target_is_running "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-starting ${_jail}..." bastille start "${_jail}" - else + else + info "\n[${_jail}]:" error_notify "Jail is not running." error_continue "Use [-a|--auto] to auto-start the jail." fi + + info "\n[${_jail}]:" jexec -l "${_jail}" /usr/sbin/sysrc "$@" -done +done \ No newline at end of file diff --git a/usr/local/share/bastille/tags.sh b/usr/local/share/bastille/tags.sh index 85dd8894..5aa0b757 100644 --- a/usr/local/share/bastille/tags.sh +++ b/usr/local/share/bastille/tags.sh @@ -56,7 +56,7 @@ while [ "$#" -gt 0 ]; do shift ;; -*) - error_exit "Unknown Option: \"${1}\"" + error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; *) break @@ -118,5 +118,4 @@ for _jail in ${JAILS}; do ;; esac -done - +done \ No newline at end of file diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 51eca57e..8b9a7e0e 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -35,6 +35,7 @@ usage() { error_notify "Usage: bastille template [option(s)] TARGET [--convert|project/template]" cat << EOF + Options: -a | --auto Auto mode. Start/stop jail(s) if required. @@ -45,6 +46,7 @@ EOF } post_command_hook() { + _jail=$1 _cmd=$2 _args=$3 @@ -110,7 +112,7 @@ render() { echo "Rendering File: ${_file_path}" eval "sed -i '' ${ARG_REPLACEMENTS} '${_file_path}'" else - warn "Path not found for render: ${2}" + warn "[WARNING]: Path not found for render: ${2}" fi } @@ -123,7 +125,7 @@ line_in_file() { echo "${_line}" >> "${_jailpath}/${_filepath}" fi else - warn "Path not found for line_in_file: ${_filepath}" + warn "[WARNING]: Path not found for line_in_file: ${_filepath}" fi } @@ -131,13 +133,13 @@ line_in_file() { AUTO=0 while [ "$#" -gt 0 ]; do case "${1}" in - -h|--help|help) - usage - ;; - -a|--auto) - AUTO=1 - shift - ;; + -h|--help|help) + usage + ;; + -a|--auto) + AUTO=1 + shift + ;; -x|--debug) enable_debug shift @@ -147,7 +149,7 @@ while [ "$#" -gt 0 ]; do case ${_opt} in a) AUTO=1 ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -158,7 +160,7 @@ while [ "$#" -gt 0 ]; do esac done -if [ $# -lt 2 ]; then +if [ "$#" -lt 2 ]; then usage fi @@ -175,11 +177,11 @@ bastille_root_check # Special case conversion of hook-style template files into a Bastillefile. -- cwells if [ "${TARGET}" = '--convert' ]; then if [ -d "${TEMPLATE}" ]; then # A relative path was provided. -- cwells - cd "${TEMPLATE}" || error_exit "Failed to change to directory: ${TEMPLATE}" + cd "${TEMPLATE}" || error_exit "[ERROR]: Failed to change to directory: ${TEMPLATE}" elif [ -d "${bastille_template}" ]; then - cd "${bastille_template}" || error_exit "Failed to change to directory: ${TEMPLATE}" + cd "${bastille_template}" || error_exit "[ERROR]: Failed to change to directory: ${TEMPLATE}" else - error_exit "Template not found: ${TEMPLATE}" + error_exit "[ERROR]: Template not found: ${TEMPLATE}" fi echo "Converting template: ${TEMPLATE}" @@ -217,7 +219,7 @@ if [ "${TARGET}" = '--convert' ]; then fi done - info "Template converted: ${TEMPLATE}" + info "\nTemplate converted: ${TEMPLATE}" exit 0 else set_target "${TARGET}" @@ -229,7 +231,7 @@ case ${TEMPLATE} in if [ ! -d "${bastille_templatesdir}/${TEMPLATE_DIR}" ]; then info "Bootstrapping ${TEMPLATE}..." if ! bastille bootstrap "${TEMPLATE}"; then - error_exit "Failed to bootstrap template: ${TEMPLATE}" + error_exit "[ERROR]: Failed to bootstrap template: ${TEMPLATE}" fi fi TEMPLATE="${TEMPLATE_DIR}" @@ -238,14 +240,14 @@ case ${TEMPLATE} in */*) if [ ! -d "${bastille_templatesdir}/${TEMPLATE}" ]; then if [ ! -d ${TEMPLATE} ]; then - error_exit "${TEMPLATE} not found." + error_exit "[ERROR]: ${TEMPLATE} not found." else bastille_template=${TEMPLATE} fi fi ;; *) - error_exit "Template name/URL not recognized." + error_exit "[ERROR]: Template name/URL not recognized." esac # Check for an --arg-file parameter. -- cwells @@ -265,22 +267,22 @@ for _script_arg in "$@"; do done if [ -n "${ARG_FILE}" ] && [ ! -f "${ARG_FILE}" ]; then - error_exit "File not found: ${ARG_FILE}" + error_exit "[ERROR]: File not found: ${ARG_FILE}" fi for _jail in ${JAILS}; do - info "\n[${_jail}]:" - check_target_is_running "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-starting ${_jail}..." bastille start "${_jail}" - else + else + info "\n[${_jail}]:" error_notify "Jail is not running." error_continue "Use [-a|--auto] to auto-start the jail." fi + + info "\n[${_jail}]:" - info "Applying template: ${TEMPLATE}..." + echo "Applying template: ${TEMPLATE}..." ## get jail ip4 and ip6 values bastille_jail_path=$(/usr/sbin/jls -j "${_jail}" path) @@ -406,7 +408,7 @@ for _jail in ${JAILS}; do if ! eval "bastille ${_cmd} ${_jail} ${_args}"; then set +f unset IFS - error_exit "Failed to execute command: ${_cmd}" + error_exit "[ERROR]: Failed to execute command: ${_cmd}" fi post_command_hook "${_jail}" "${_cmd}" "${_args}" @@ -450,9 +452,9 @@ for _jail in ${JAILS}; do info "[${_jail}]:${_hook} -- START" if [ "${_hook}" = 'CMD' ] || [ "${_hook}" = 'PRE' ]; then - bastille cmd "${_jail}" /bin/sh < "${bastille_template}/${_hook}" || error_exit "Failed to execute command." + bastille cmd "${_jail}" /bin/sh < "${bastille_template}/${_hook}" || error_exit "[ERROR]: Failed to execute command." elif [ "${_hook}" = 'PKG' ]; then - bastille pkg "${_jail}" install -y "$(cat "${bastille_template}/PKG")" || error_exit "Failed to install packages." + bastille pkg "${_jail}" install -y "$(cat "${bastille_template}/PKG")" || error_exit "[ERROR]: Failed to install packages." bastille pkg "${_jail}" audit -F else while read _line; do @@ -462,7 +464,7 @@ for _jail in ${JAILS}; do # Replace "arg" variables in this line with the provided values. -- cwells _line=$(echo "${_line}" | eval "sed ${ARG_REPLACEMENTS}") eval "_args=\"${_args_template}\"" - bastille "${_cmd}" "${_jail}" "${_args}" || error_exit "Failed to execute command." + bastille "${_cmd}" "${_jail}" "${_args}" || error_exit "[ERROR]: Failed to execute command." done < "${bastille_template}/${_hook}" fi info "[${_jail}]:${_hook} -- END" @@ -470,8 +472,6 @@ for _jail in ${JAILS}; do fi done - info "Template applied: ${TEMPLATE}" + info "\nTemplate applied: ${TEMPLATE}" -done - -echo \ No newline at end of file +done \ No newline at end of file diff --git a/usr/local/share/bastille/top.sh b/usr/local/share/bastille/top.sh index 20afe19f..65879c88 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 "[ERROR]: Unknown Option: \"${1}\"" esac done shift @@ -85,16 +85,14 @@ TARGET="${1}" bastille_root_check set_target_single "${TARGET}" -info "\n[${TARGET}]:" - check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-starting ${TARGET}..." bastille start "${TARGET}" -else +else + info "\n[${TARGET}]:" error_notify "Jail is not running." error_exit "Use [-a|--auto] to auto-start the jail." fi -jexec -l "${TARGET}" /usr/bin/top +info "\n[${TARGET}]:" -echo +jexec -l "${TARGET}" /usr/bin/top \ No newline at end of file diff --git a/usr/local/share/bastille/umount.sh b/usr/local/share/bastille/umount.sh index 43d4512c..7b56da38 100644 --- a/usr/local/share/bastille/umount.sh +++ b/usr/local/share/bastille/umount.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 "[ERROR]: Unknown Option: \"${1}\"" esac done shift @@ -88,17 +88,16 @@ set_target "${TARGET}" for _jail in ${JAILS}; do - info "\n[${_jail}]:" - + # Validate jail state check_target_is_running "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-starting ${_jail}..." bastille start "${_jail}" else + info "\n[${TARGET}]:" error_notify "Jail is not running." error_continue "Use [-a|--auto] to auto-start the jail." fi - info "[${_jail}]:" + info "\n[${_jail}]:" _jailpath="$( echo "${bastille_jailsdir}/${_jail}/root/${MOUNT_PATH}" 2>/dev/null | sed 's#//#/#' | sed 's#\\##g')" _mount="$( mount | grep -Eo "[[:blank:]]${_jailpath}[[:blank:]]" )" @@ -107,18 +106,18 @@ for _jail in ${JAILS}; do # Exit if mount point non-existent if [ -z "${_mount}" ] && [ -z "${_fstab_entry}" ]; then - error_continue "The specified mount point does not exist." + error_continue "[ERROR]: The specified mount point does not exist." fi # Unmount if [ -n "${_mount}" ]; then - umount "${_jailpath}" || error_continue "Failed to unmount volume: ${MOUNT_PATH}" + umount "${_jailpath}" || error_continue "[ERROR]: Failed to unmount volume: ${MOUNT_PATH}" fi # Remove entry from fstab if [ -n "${_fstab_entry}" ]; then if ! sed -E -i '' "\, +${_jailpath_fstab} +,d" "${bastille_jailsdir}/${_jail}/fstab"; then - error_continue "Failed to delete fstab entry: ${MOUNT_PATH}" + error_continue "[ERROR]: Failed to delete fstab entry: ${MOUNT_PATH}" fi fi @@ -129,6 +128,4 @@ for _jail in ${JAILS}; do echo "Unmounted: ${_jailpath}" -done - -echo \ No newline at end of file +done \ No newline at end of file diff --git a/usr/local/share/bastille/update.sh b/usr/local/share/bastille/update.sh index 85ded66c..902acd7f 100644 --- a/usr/local/share/bastille/update.sh +++ b/usr/local/share/bastille/update.sh @@ -75,7 +75,7 @@ while [ "$#" -gt 0 ]; do a) AUTO=1 ;; f) OPTION="-F" ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -91,12 +91,11 @@ TARGET="${1}" bastille_root_check if [ -f "/bin/midnightbsd-version" ]; then - echo -e "${COLOR_RED}Not yet supported on MidnightBSD.${COLOR_RESET}" - exit 1 + error_exit "[ERROR]: Not yet supported on MidnightBSD." fi if freebsd-version | grep -qi HBSD; then - error_exit "Not yet supported on HardenedBSD." + error_exit "[ERROR]: Not yet supported on HardenedBSD." fi # Check for alternate/unsupported archs @@ -107,31 +106,38 @@ arch_check() { } jail_check() { + # Check if the jail is thick and is running set_target_single "${TARGET}" + check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-starting ${TARGET}..." bastille start "${TARGET}" else + info "\n[${TARGET}]:" error_notify "Jail is not running." error_exit "Use [-a|--auto] to auto-start the jail." fi + + info "\n[${TARGET}]:" + if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then - error_notify "${TARGET} is not a thick container." + error_notify "[ERROR]: ${TARGET} is not a thick container." error_exit "See 'bastille update RELEASE' to update thin jails." fi } jail_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." + error_exit "[ERROR]: Can't determine '${TARGET}' version." else env PAGER="/bin/cat" freebsd-update ${OPTION} \ --not-running-from-cron \ @@ -144,9 +150,11 @@ 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}" @@ -166,29 +174,32 @@ release_update() { -f "${_freebsd_update_conf}" \ install --currently-running "${TARGET_TRIM}" else - error_exit "${TARGET} not found. See 'bastille bootstrap RELEASE'." + error_exit "[ERROR]: ${TARGET} not found. See 'bastille bootstrap RELEASE'." fi } template_update() { + # Update a template _template_path=${bastille_templatesdir}/${BASTILLE_TEMPLATE} - if [ -d $_template_path ]; then - info "[${BASTILLE_TEMPLATE}]:" - git -C $_template_path pull ||\ - error_notify "${BASTILLE_TEMPLATE} update unsuccessful." + if [ -d $_template_path ]; then + info "\n[${BASTILLE_TEMPLATE}]:" + if ! git -C $_template_path pull; then + error_exit "[ERROR]: ${BASTILLE_TEMPLATE} update unsuccessful." + fi bastille verify "${BASTILLE_TEMPLATE}" else - error_exit "${BASTILLE_TEMPLATE} not found. See 'bastille bootstrap'." + error_exit "[ERROR]: ${BASTILLE_TEMPLATE} not found. See 'bastille bootstrap'." fi } templates_update() { + # Update all templates _updated_templates=0 if [ -d ${bastille_templatesdir} ]; then - # shellcheck disable=SC2045 + # 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 }') @@ -200,9 +211,9 @@ templates_update() { fi if [ "$_updated_templates" -ne "0" ]; then - info "$_updated_templates templates updated." + info "\n$_updated_templates templates updated." else - error_exit "no templates found. See 'bastille bootstrap'." + error_exit "[ERROR]: No templates found. See 'bastille bootstrap'." fi } @@ -216,9 +227,6 @@ elif echo "${TARGET}" | grep -q "[0-9]\{2\}.[0-9]-RELEASE"; then arch_check release_update else - info "\n[${TARGET}]:" jail_check jail_update "${TARGET}" -fi - -echo \ No newline at end of file +fi \ No newline at end of file diff --git a/usr/local/share/bastille/upgrade.sh b/usr/local/share/bastille/upgrade.sh index 3edaf8cb..f22099a8 100644 --- a/usr/local/share/bastille/upgrade.sh +++ b/usr/local/share/bastille/upgrade.sh @@ -72,7 +72,7 @@ while [ "$#" -gt 0 ]; do a) AUTO=1 ;; f) OPTION="-F" ;; x) enable_debug ;; - *) error_exit "Unknown Option: \"${1}\"" ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; esac done shift @@ -95,55 +95,63 @@ set_target_single "${TARGET}" # Check for unsupported actions if [ -f "/bin/midnightbsd-version" ]; then - echo -e "${COLOR_RED}Not yet supported on MidnightBSD.${COLOR_RESET}" - exit 1 + error_exit "[ERROR]: Not yet supported on MidnightBSD." fi if freebsd-version | grep -qi HBSD; then - error_exit "Not yet supported on HardenedBSD." + error_exit "[ERROR]: Not yet supported on HardenedBSD." fi thick_jail_check() { + local _jail="${1}" - # Check if the jail is thick and is running + + # Validate jail state check_target_is_running "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-starting ${_jail}..." bastille start "${_jail}" else + info "\n[${_jail}]:" error_notify "Jail is not running." error_exit "Use [-a|--auto] to auto-start the jail." fi } thin_jail_check() { + local _jail="${1}" - # Check if the jail is thick and is running + + # Validate jail state check_target_is_stopped "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - echo "Auto-stopping ${_jail}..." bastille stop "${_jail}" else + info "\n[${_jail}]:" error_notify "Jail is running." error_exit "Use [-a|--auto] to auto-stop the jail." fi } release_check() { + local _release="${1}" + # Validate the release if ! echo "${_release}" | grep -q "[0-9]\{2\}.[0-9]-[RELEASE,BETA,RC]"; then - error_exit "${_release} is not a valid release." + error_exit "[ERROR]: ${_release} is not a valid release." fi + # Exit if NEWRELEASE doesn't exist if [ "${THIN_JAIL}" -eq 1 ]; then if [ ! -d "${bastille_releasesdir}/${_release}" ]; then - error_notify "Release not found: ${_release}" + error_notify "[ERROR]: Release not found: ${_release}" error_exit "See 'bastille bootstrap ${_release} to bootstrap the release." fi fi } jail_upgrade() { + local _jailname="${1}" + if [ "${THIN_JAIL}" -eq 1 ]; then local _oldrelease="$(bastille config ${_jailname} get osrelease)" else @@ -166,8 +174,8 @@ jail_upgrade() { if [ "${AUTO}" -eq 1 ]; then bastille start "${_jailname}" fi - info "Upgraded ${_jailname}: ${_oldrelease} -> ${_newrelease}" - info "See 'bastille etcupdate TARGET' to update /etc/rc.conf" + info "\nUpgraded ${_jailname}: ${_oldrelease} -> ${_newrelease}" + echo "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 \ @@ -179,16 +187,17 @@ jail_upgrade() { # Update "osrelease" entry inside jail.conf sed -i '' "/osrelease/ s|${_oldrelease}|${_newrelease}|g" "${bastille_jailsdir}/${_jailname}/jail.conf" - echo - echo -e "${COLOR_YELLOW}Please run 'bastille upgrade ${_jailname} install', restart the jail, then run 'bastille upgrade ${_jailname} install' again to finish installing updates.${COLOR_RESET}" + warn "Please run 'bastille upgrade ${_jailname} install', restart the jail, then run 'bastille upgrade ${_jailname} install' again to finish installing updates." fi } jail_updates_install() { + local _jailname="${1}" local _jailpath="${bastille_jailsdir}/${_jailname}/root" 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}/${_jailname}" ]; then env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron \ @@ -197,7 +206,7 @@ jail_updates_install() { -f "${_freebsd_update_conf}" \ install else - error_exit "${TARGET} not found. See 'bastille bootstrap RELEASE'." + error_exit "[ERROR]: ${_jailname} not found. See 'bastille bootstrap RELEASE'." fi } @@ -207,8 +216,6 @@ if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir THIN_JAIL=1 fi -info "\n[${TARGET}]:" - # Check what we should upgrade if [ "${NEWRELEASE}" = "install" ]; then if [ "${THIN_JAIL}" -eq 1 ]; then @@ -216,6 +223,7 @@ if [ "${NEWRELEASE}" = "install" ]; then else thick_jail_check "${TARGET}" fi + info "\n[${TARGET}]:" jail_updates_install "${TARGET}" else release_check "${NEWRELEASE}" @@ -224,7 +232,6 @@ else else thick_jail_check "${TARGET}" fi + info "\n[${TARGET}]:" jail_upgrade "${TARGET}" "${NEWRELEASE}" -fi - -echo \ No newline at end of file +fi \ No newline at end of file diff --git a/usr/local/share/bastille/verify.sh b/usr/local/share/bastille/verify.sh index 13342cb1..6b72c25b 100644 --- a/usr/local/share/bastille/verify.sh +++ b/usr/local/share/bastille/verify.sh @@ -45,22 +45,24 @@ EOF } verify_release() { + if [ -f "/bin/midnightbsd-version" ]; then - echo -e "${COLOR_RED}Not yet supported on MidnightBSD.${COLOR_RESET}" - exit 1 + error_exit "[ERROR]: Not yet supported on MidnightBSD." fi + if freebsd-version | grep -qi HBSD; then - error_exit "Not yet supported on HardenedBSD." + error_exit "[ERROR]: Not yet supported on HardenedBSD." fi if [ -d "${bastille_releasesdir}/${RELEASE}" ]; then freebsd-update -b "${bastille_releasesdir}/${RELEASE}" --currently-running "${RELEASE}" IDS else - error_exit "${RELEASE} not found. See 'bastille bootstrap'." + error_exit "[ERROR]: ${RELEASE} not found. See 'bastille bootstrap'." fi } handle_template_include() { + case ${TEMPLATE_INCLUDE} in http?://*/*/*) bastille bootstrap "${TEMPLATE_INCLUDE}" @@ -71,12 +73,13 @@ handle_template_include() { bastille verify "${BASTILLE_TEMPLATE_USER}/${BASTILLE_TEMPLATE_REPO}" ;; *) - error_exit "Template INCLUDE content not recognized." + error_exit "[ERROR]: Template INCLUDE content not recognized." ;; esac } verify_template() { + _template_path=${bastille_templatesdir}/${BASTILLE_TEMPLATE} _hook_validate=0 @@ -84,22 +87,20 @@ verify_template() { _path=${_template_path}/${_hook} if [ -s "${_path}" ]; then _hook_validate=$((_hook_validate+1)) - info "Detected ${_hook} hook." + info "\nDetected ${_hook} hook." ## line count must match newline count # shellcheck disable=SC2046 # shellcheck disable=SC3003 if [ $(wc -l "${_path}" | awk '{print $1}') -ne "$(tr -d -c '\n' < "${_path}" | wc -c)" ]; then info "[${_hook}]:" - error_notify "${BASTILLE_TEMPLATE}:${_hook} [failed]." + error_notify "[ERROR]: ${BASTILLE_TEMPLATE}:${_hook} [failed]." error_notify "Line numbers don't match line breaks." - echo error_exit "Template validation failed." ## if INCLUDE; recursive verify elif [ "${_hook}" = 'INCLUDE' ]; then info "[${_hook}]:" cat "${_path}" - echo while read _include; do info "[${_hook}]:[${_include}]:" TEMPLATE_INCLUDE="${_include}" @@ -110,7 +111,6 @@ verify_template() { elif [ "${_hook}" = 'OVERLAY' ]; then info "[${_hook}]:" cat "${_path}" - echo while read _dir; do info "[${_hook}]:[${_dir}]:" if [ -x "/usr/local/bin/tree" ]; then @@ -118,7 +118,6 @@ verify_template() { else find "${_template_path}/${_dir}" -print | sed -e 's;[^/]*/;|___;g;s;___|; |;g' fi - echo done < "${_path}" elif [ "${_hook}" = 'Bastillefile' ]; then info "[${_hook}]:" @@ -131,41 +130,38 @@ verify_template() { handle_template_include fi done < "${_path}" - echo else info "[${_hook}]:" cat "${_path}" - echo fi fi done - ## remove bad templates + # Remove bad templates if [ "${_hook_validate}" -lt 1 ]; then - error_notify "No valid template hooks found." - error_notify "Template discarded." rm -rf "${_template_path}" - exit 1 + error_notify "[ERROR]: No valid template hooks found." + error_exit "Template discarded." fi ## if validated; ready to use if [ "${_hook_validate}" -gt 0 ]; then - info "Template ready to use." + info "\nTemplate ready to use." fi } # Handle options. while [ "$#" -gt 0 ]; do case "${1}" in - -h|--help|help) - usage - ;; + -h|--help|help) + usage + ;; -x|--debug) enable_debug shift ;; -*) - error_exit "Unknown Option: \"${1}\"" + error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; *) break @@ -200,4 +196,4 @@ case "${1}" in ;; esac -echo +echo \ No newline at end of file diff --git a/usr/local/share/bastille/zfs.sh b/usr/local/share/bastille/zfs.sh index 37cd8f0b..fb0aa707 100644 --- a/usr/local/share/bastille/zfs.sh +++ b/usr/local/share/bastille/zfs.sh @@ -45,54 +45,65 @@ EOF } zfs_snapshot() { -for _jail in ${JAILS}; do - info "\n[${_jail}]:" + for _jail in ${JAILS}; do + + info "\n[${_jail}]:" - # shellcheck disable=SC2140 - zfs snapshot -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}"@"${TAG}" + # shellcheck disable=SC2140 + zfs snapshot -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}"@"${TAG}" -done + done + } zfs_destroy_snapshot() { -for _jail in ${JAILS}; do - info "\n[${_jail}]:" + for _jail in ${JAILS}; do + + info "\n[${_jail}]:" - # shellcheck disable=SC2140 - zfs destroy -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}"@"${TAG}" + # shellcheck disable=SC2140 + zfs destroy -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}"@"${TAG}" + + done -done } zfs_set_value() { -for _jail in ${JAILS}; do - info "\n[${_jail}]:" + for _jail in ${JAILS}; do + + info "\n[${_jail}]:" - zfs "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" + zfs "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" -done + done + } zfs_get_value() { -for _jail in ${JAILS}; do - info "\n[${_jail}]:" - zfs get "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" + for _jail in ${JAILS}; do + + info "\n[${_jail}]:" + + zfs get "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" -done + done + } zfs_disk_usage() { -for _jail in ${JAILS}; do - info "\n[${_jail}]:" + for _jail in ${JAILS}; do + + info "\n[${_jail}]:" - zfs list -t all -o name,used,avail,refer,mountpoint,compress,ratio -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" + zfs list -t all -o name,used,avail,refer,mountpoint,compress,ratio -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" -done + done + } @@ -107,7 +118,7 @@ while [ "$#" -gt 0 ]; do shift ;; -*) - error_notify "Unknown Option: \"${1}\"" + error_notify "[ERROR]: Unknown Option: \"${1}\"" usage ;; *) @@ -128,12 +139,12 @@ set_target "${TARGET}" # Check if ZFS is enabled if ! checkyesno bastille_zfs_enable; then - error_exit "ZFS not enabled." + error_exit "[ERROR]: ZFS not enabled." fi # Check if zpool is defined if [ -z "${bastille_zfs_zpool}" ]; then - error_exit "ZFS zpool not defined." + error_exit "[ERROR]: ZFS zpool not defined." fi case "${ACTION}" in @@ -159,6 +170,4 @@ case "${ACTION}" in *) usage ;; -esac - -echo \ No newline at end of file +esac \ No newline at end of file