diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index 750f7b49..1542cdcf 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -114,7 +114,7 @@ validate_ip() { 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 "\nValid: (${IP})." @@ -130,7 +130,7 @@ validate_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 "\nValid: (${IP})." fi @@ -382,7 +382,10 @@ update_jailconf_vnet() { clone_jail() { if ! [ -d "${bastille_jailsdir}/${NEWNAME}" ]; then + if checkyesno bastille_zfs_enable; then + + # Validate jail state if [ "${LIVE}" -eq 1 ]; then if ! check_target_is_running "${TARGET}"; then error_exit "[-l|--live] can only be used with a running jail." diff --git a/usr/local/share/bastille/config.sh b/usr/local/share/bastille/config.sh index f46c6ff9..abc54c66 100644 --- a/usr/local/share/bastille/config.sh +++ b/usr/local/share/bastille/config.sh @@ -115,7 +115,9 @@ 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 @@ -242,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/create.sh b/usr/local/share/bastille/create.sh index e8ebf791..d61ed30d 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,8 +60,10 @@ 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!" elif [ "${NAME_VERIFY}" != "${NAME_SANITY}" ]; then @@ -71,14 +74,16 @@ validate_name() { } 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 +95,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 +120,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 +157,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})." fi } validate_release() { + ## ensure the user set the Linux(experimental) option explicitly if [ -n "${UBUNTU}" ]; then if [ -z "${LINUX_JAIL}" ]; then @@ -185,6 +199,7 @@ validate_release() { } generate_minimal_conf() { + cat << EOF > "${bastille_jail_conf}" ${NAME} { host.hostname = ${NAME}; @@ -196,6 +211,7 @@ EOF } generate_jail_conf() { + if [ "$(sysctl -n security.jail.jailed)" -eq 1 ]; then devfs_ruleset_value=0 else @@ -224,6 +240,7 @@ EOF } generate_linux_jail_conf() { + cat << EOF > "${bastille_jail_conf}" ${NAME} { host.hostname = ${NAME}; @@ -247,12 +264,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 +294,7 @@ EOF } post_create_jail() { + # Common config checks and settings. # Using relative paths here. @@ -310,6 +331,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 @@ -487,7 +509,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 +571,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 @@ -778,16 +800,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." 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 +817,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 +829,7 @@ else fi fi -## validate jail name +# Validate jail name if [ -n "${NAME}" ]; then validate_name fi @@ -813,11 +837,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 +877,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 +961,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 +987,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 +1029,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/verify.sh b/usr/local/share/bastille/verify.sh index 36dde162..11b8b847 100644 --- a/usr/local/share/bastille/verify.sh +++ b/usr/local/share/bastille/verify.sh @@ -47,9 +47,9 @@ EOF verify_release() { if [ -f "/bin/midnightbsd-version" ]; then - echo -e "${COLOR_RED}Not yet supported on MidnightBSD.${COLOR_RESET}" - exit 1 + error_exit "Not yet supported on MidnightBSD." fi + if freebsd-version | grep -qi HBSD; then error_exit "Not yet supported on HardenedBSD." fi @@ -96,13 +96,11 @@ verify_template() { info "[${_hook}]:" error_notify "${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}" @@ -113,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 @@ -121,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}]:" @@ -134,21 +130,18 @@ 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 "No valid template hooks found." + error_exit "Template discarded." fi ## if validated; ready to use @@ -160,9 +153,9 @@ verify_template() { # Handle options. while [ "$#" -gt 0 ]; do case "${1}" in - -h|--help|help) - usage - ;; + -h|--help|help) + usage + ;; -x|--debug) enable_debug shift @@ -201,4 +194,4 @@ case "${1}" in *) usage ;; -esac +esac \ No newline at end of file diff --git a/usr/local/share/bastille/zfs.sh b/usr/local/share/bastille/zfs.sh index 9c139e39..d48d95d7 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 + }