From dd9e55bb9b403193181b105813a3008ddf8275fe Mon Sep 17 00:00:00 2001 From: Jose Date: Tue, 24 Nov 2020 08:38:49 -0400 Subject: [PATCH 01/26] Update command enhancement and code improvements --- usr/local/share/bastille/update.sh | 73 ++++++++++++++++++++--------- usr/local/share/bastille/upgrade.sh | 2 +- 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/usr/local/share/bastille/update.sh b/usr/local/share/bastille/update.sh index 34e3c641..d6a00ac3 100644 --- a/usr/local/share/bastille/update.sh +++ b/usr/local/share/bastille/update.sh @@ -42,41 +42,72 @@ help|-h|--help) ;; esac -if [ $# -gt 1 ] || [ $# -lt 1 ]; then +if [ $# -gt 2 ] || [ $# -lt 1 ]; then usage fi TARGET="${1}" -shift +OPTION="${2}" + +# Handle options +case "${OPTION}" in + -f|--force) + OPTION="-F" + ;; + *) + OPTION= + ;; +esac + +# Check for unsupported actions +if [ "${TARGET}" = "ALL" ]; then + error_exit "Batch upgrade is unsupported." +fi if freebsd-version | grep -qi HBSD; then error_exit "Not yet supported on HardenedBSD." fi -if [ -d "${bastille_jailsdir}/${TARGET}" ]; then - if ! grep -qw ".bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then - if [ "$(jls name | awk "/^${TARGET}$/")" ]; then - # Update a thick container. - CURRENT_VERSION=$(/usr/sbin/jexec -l "${TARGET}" freebsd-version 2>/dev/null) - if [ -z "${CURRENT_VERSION}" ]; then - error_exit "Can't determine '${TARGET}' version." - else - env PAGER="/bin/cat" freebsd-update --not-running-from-cron -b "${bastille_jailsdir}/${TARGET}/root" \ - fetch install --currently-running "${CURRENT_VERSION}" - fi - else - error_notify "${TARGET} is not running." - error_exit "See 'bastille start ${TARGET}'." - fi +jail_check() { + # Check if the jail is thick and is running + if [ ! "$(jls name | awk "/^${TARGET}$/")" ]; then + error_exit "[${TARGET}]: Not started. See 'bastille start ${TARGET}'." else - error_exit "${TARGET} is not a thick container." + if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then + error_exit "${TARGET} is not a thick container." + fi fi -else +} + +jail_update() { + # Update a thick container + if [ -d "${bastille_jailsdir}/${TARGET}" ]; then + jail_check + CURRENT_VERSION=$(/usr/sbin/jexec -l "${TARGET}" freebsd-version 2>/dev/null) + if [ -z "${CURRENT_VERSION}" ]; then + error_exit "Can't determine '${TARGET}' version." + else + env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_jailsdir}/${TARGET}/root" \ + fetch install --currently-running "${CURRENT_VERSION}" + fi + else + error_exit "${TARGET} not found. See 'bastille bootstrap'." + fi +} + +release_update() { + # Update a release base(affects child containers) if [ -d "${bastille_releasesdir}/${TARGET}" ]; then - # Update container base(affects child containers). - env PAGER="/bin/cat" freebsd-update --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" \ + env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" \ fetch install --currently-running "${TARGET}" else error_exit "${TARGET} not found. See 'bastille bootstrap'." fi +} + +# Check what we should update +if echo "${TARGET}" | grep -q "[0-9]\{2\}.[0-9]-RELEASE"; then + release_update +else + jail_update fi diff --git a/usr/local/share/bastille/upgrade.sh b/usr/local/share/bastille/upgrade.sh index 56b32a01..dbd0ee9b 100644 --- a/usr/local/share/bastille/upgrade.sh +++ b/usr/local/share/bastille/upgrade.sh @@ -74,7 +74,7 @@ jail_check() { if [ ! "$(jls name | awk "/^${TARGET}$/")" ]; then error_exit "[${TARGET}]: Not started. See 'bastille start ${TARGET}'." else - if cat "${bastille_jailsdir}/${TARGET}/fstab" 2>/dev/null | grep -w "${TARGET}" | grep -qw "/.*/.bastille"; then + if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then error_exit "${TARGET} is not a thick container." fi fi From 8b4d18f8f3a1acf8e530d383650804bcefd1869e Mon Sep 17 00:00:00 2001 From: Chris Wells Date: Wed, 25 Nov 2020 21:19:08 -0500 Subject: [PATCH 02/26] Create info() and warn() for cleaner print statements. --- usr/local/bin/bastille | 2 +- usr/local/share/bastille/bootstrap.sh | 18 +++++----- usr/local/share/bastille/clone.sh | 10 +++--- usr/local/share/bastille/cmd.sh | 2 +- usr/local/share/bastille/common.sh | 8 +++++ usr/local/share/bastille/console.sh | 2 +- usr/local/share/bastille/convert.sh | 4 +-- usr/local/share/bastille/cp.sh | 2 +- usr/local/share/bastille/create.sh | 20 +++++------ usr/local/share/bastille/destroy.sh | 10 +++--- usr/local/share/bastille/export.sh | 8 ++--- usr/local/share/bastille/htop.sh | 2 +- usr/local/share/bastille/import.sh | 52 +++++++++++++-------------- usr/local/share/bastille/limits.sh | 2 +- usr/local/share/bastille/mount.sh | 18 +++++----- usr/local/share/bastille/pkg.sh | 2 +- usr/local/share/bastille/rename.sh | 4 +-- usr/local/share/bastille/service.sh | 2 +- usr/local/share/bastille/start.sh | 2 +- usr/local/share/bastille/stop.sh | 2 +- usr/local/share/bastille/sysrc.sh | 2 +- usr/local/share/bastille/template.sh | 26 +++++++------- usr/local/share/bastille/top.sh | 2 +- usr/local/share/bastille/umount.sh | 2 +- usr/local/share/bastille/verify.sh | 16 ++++----- usr/local/share/bastille/zfs.sh | 8 ++--- 26 files changed, 118 insertions(+), 110 deletions(-) diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index 62b97bb7..b984f342 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -127,7 +127,7 @@ shift # Handle special-case commands first. case "${CMD}" in version|-v|--version) - echo -e "${COLOR_GREEN}${BASTILLE_VERSION}${COLOR_RESET}" + info "${BASTILLE_VERSION}" exit 0 ;; help|-h|--help) diff --git a/usr/local/share/bastille/bootstrap.sh b/usr/local/share/bastille/bootstrap.sh index 7608cc1d..35ee66f9 100644 --- a/usr/local/share/bastille/bootstrap.sh +++ b/usr/local/share/bastille/bootstrap.sh @@ -68,7 +68,7 @@ validate_release_url() { if ! fetch -qo /dev/null "${UPSTREAM_URL}/MANIFEST" 2>/dev/null; then error_exit "Unable to fetch MANIFEST. See 'bootstrap urls'." fi - echo -e "${COLOR_GREEN}Bootstrapping ${PLATFORM_OS} distfiles...${COLOR_RESET}" + info "Bootstrapping ${PLATFORM_OS} distfiles..." # Alternate RELEASE/ARCH fetch support if [ "${OPTION}" = "--i386" -o "${OPTION}" = "--32bit" ]; then @@ -203,7 +203,7 @@ bootstrap_release() { if [ -z "${bastille_bootstrap_archives}" ]; then error_exit "Bootstrap appears complete." else - echo -e "${COLOR_GREEN}Bootstrapping additional distfiles...${COLOR_RESET}" + info "Bootstrapping additional distfiles..." fi fi @@ -211,7 +211,7 @@ bootstrap_release() { ## check if the dist files already exists then extract FETCH_VALIDATION="0" if [ -f "${bastille_cachedir}/${RELEASE}/${_archive}.txz" ]; then - echo -e "${COLOR_GREEN}Extracting ${PLATFORM_OS} ${RELEASE} ${_archive}.txz.${COLOR_RESET}" + 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" @@ -267,15 +267,15 @@ bootstrap_release() { rm "${bastille_cachedir}/${RELEASE}/${_archive}.txz" error_exit "Failed validation for ${_archive}.txz. Please retry bootstrap!" else - echo -e "${COLOR_GREEN}Validated checksum for ${RELEASE}:${_archive}.txz.${COLOR_RESET}" - echo -e "${COLOR_GREEN}MANIFEST:${SHA256_DIST}${COLOR_RESET}" - echo -e "${COLOR_GREEN}DOWNLOAD:${SHA256_FILE}${COLOR_RESET}" + info "Validated checksum for ${RELEASE}: ${_archive}.txz" + info "MANIFEST: ${SHA256_DIST}" + info "DOWNLOAD: ${SHA256_FILE}" fi fi ## extract the fetched dist files if [ -f "${bastille_cachedir}/${RELEASE}/${_archive}.txz" ]; then - echo -e "${COLOR_GREEN}Extracting ${PLATFORM_OS} ${RELEASE} ${_archive}.txz.${COLOR_RESET}" + 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" @@ -288,8 +288,8 @@ bootstrap_release() { done echo - echo -e "${COLOR_GREEN}Bootstrap successful.${COLOR_RESET}" - echo -e "${COLOR_GREEN}See 'bastille --help' for available commands.${COLOR_RESET}" + info "Bootstrap successful." + info "See 'bastille --help' for available commands." echo } diff --git a/usr/local/share/bastille/clone.sh b/usr/local/share/bastille/clone.sh index e3badf25..bc9c34e6 100644 --- a/usr/local/share/bastille/clone.sh +++ b/usr/local/share/bastille/clone.sh @@ -54,7 +54,7 @@ validate_ip() { IP6_MODE="disable" ip6=$(echo "${IP}" | grep -E '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$))') if [ -n "${ip6}" ]; then - echo -e "${COLOR_GREEN}Valid: (${ip6}).${COLOR_RESET}" + info "Valid: (${ip6})." IPX_ADDR="ip6.addr" IP6_MODE="new" else @@ -69,9 +69,9 @@ validate_ip() { fi done if ifconfig | grep -qw "${TEST_IP}"; then - echo -e "${COLOR_YELLOW}Warning: ip address already in use (${TEST_IP}).${COLOR_RESET}" + warn "Warning: IP address already in use (${TEST_IP})." else - echo -e "${COLOR_GREEN}Valid: (${IP}).${COLOR_RESET}" + info "Valid: (${IP})." fi else error_exit "Invalid: (${IP})." @@ -144,7 +144,7 @@ update_fstab() { clone_jail() { # Attempt container clone - echo -e "${COLOR_GREEN}Attempting to clone '${TARGET}' to ${NEWNAME}...${COLOR_RESET}" + info "Attempting to clone '${TARGET}' to ${NEWNAME}..." if ! [ -d "${bastille_jailsdir}/${NEWNAME}" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then if [ -n "${bastille_zfs_zpool}" ]; then @@ -183,7 +183,7 @@ clone_jail() { if [ "$?" -ne 0 ]; then error_exit "An error has occurred while attempting to clone '${TARGET}'." else - echo -e "${COLOR_GREEN}Cloned '${TARGET}' to '${NEWNAME}' successfully.${COLOR_RESET}" + info "Cloned '${TARGET}' to '${NEWNAME}' successfully." fi } diff --git a/usr/local/share/bastille/cmd.sh b/usr/local/share/bastille/cmd.sh index dcb63506..3ebc1ad3 100644 --- a/usr/local/share/bastille/cmd.sh +++ b/usr/local/share/bastille/cmd.sh @@ -46,7 +46,7 @@ if [ $# -eq 0 ]; then fi for _jail in ${JAILS}; do - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" jexec -l "${_jail}" "$@" echo done diff --git a/usr/local/share/bastille/common.sh b/usr/local/share/bastille/common.sh index 285b843e..4dd30c1a 100644 --- a/usr/local/share/bastille/common.sh +++ b/usr/local/share/bastille/common.sh @@ -40,3 +40,11 @@ error_exit() { error_notify $@ exit 1 } + +info() { + echo -e "${COLOR_GREEN}$*${COLOR_RESET}" +} + +warn() { + echo -e "${COLOR_YELLOW}$*${COLOR_RESET}" +} diff --git a/usr/local/share/bastille/console.sh b/usr/local/share/bastille/console.sh index 149291d1..30066ade 100644 --- a/usr/local/share/bastille/console.sh +++ b/usr/local/share/bastille/console.sh @@ -65,7 +65,7 @@ validate_user() { } for _jail in ${JAILS}; do - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" if [ -n "${USER}" ]; then validate_user else diff --git a/usr/local/share/bastille/convert.sh b/usr/local/share/bastille/convert.sh index 7ecc76cf..29aa7af7 100644 --- a/usr/local/share/bastille/convert.sh +++ b/usr/local/share/bastille/convert.sh @@ -101,7 +101,7 @@ revert_convert() { start_convert() { # Attempt container conversion and handle some errors if [ -d "${bastille_jailsdir}/${TARGET}" ]; then - echo -e "${COLOR_GREEN}Converting '${TARGET}' into a thickjail, this may take a while...${COLOR_RESET}" + info "Converting '${TARGET}' into a thickjail. This may take a while..." # Set some variables RELEASE=$(grep -owE '([1-9]{2,2})\.[0-9](-RELEASE|-RELEASE-i386|-RC[1-2])|([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)' "${bastille_jailsdir}/${TARGET}/fstab") @@ -118,7 +118,7 @@ start_convert() { sed -i '' -E "s|${FSTABMOD}|# Converted from thin to thick container on $(date)|g" "${bastille_jailsdir}/${TARGET}/fstab" mv "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/root/.bastille.old" - echo -e "${COLOR_GREEN}Conversion of '${TARGET}' completed successfully!${COLOR_RESET}" + info "Conversion of '${TARGET}' completed successfully!" exit 0 else error_exit "Can't determine release version. See 'bastille bootstrap'." diff --git a/usr/local/share/bastille/cp.sh b/usr/local/share/bastille/cp.sh index 8c59ba69..3e179589 100644 --- a/usr/local/share/bastille/cp.sh +++ b/usr/local/share/bastille/cp.sh @@ -51,7 +51,7 @@ CPDEST="${2}" for _jail in ${JAILS}; do bastille_jail_path="$(jls -j "${_jail}" path)" - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" cp -av "${CPSOURCE}" "${bastille_jail_path}/${CPDEST}" RETURN="$?" if [ "${TARGET}" = "ALL" ]; then diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index 8e69a0c8..141edfba 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -56,7 +56,7 @@ validate_ip() { IP6_MODE="disable" ip6=$(echo "${IP}" | grep -E '^(([a-fA-F0-9:]+$)|([a-fA-F0-9:]+\/[0-9]{1,3}$))') if [ -n "${ip6}" ]; then - echo -e "${COLOR_GREEN}Valid: (${ip6}).${COLOR_RESET}" + info "Valid: (${ip6})." IPX_ADDR="ip6.addr" IP6_MODE="new" else @@ -72,9 +72,9 @@ validate_ip() { fi done if ifconfig | grep -qw "${TEST_IP}"; then - echo -e "${COLOR_YELLOW}Warning: ip address already in use (${TEST_IP}).${COLOR_RESET}" + warn "Warning: IP address already in use (${TEST_IP})." else - echo -e "${COLOR_GREEN}Valid: (${IP}).${COLOR_RESET}" + info "Valid: (${IP})." fi else error_exit "Invalid: (${IP})." @@ -85,7 +85,7 @@ validate_ip() { validate_netif() { local LIST_INTERFACES=$(ifconfig -l) if echo "${LIST_INTERFACES} VNET" | grep -qwo "${INTERFACE}"; then - echo -e "${COLOR_GREEN}Valid: (${INTERFACE}).${COLOR_RESET}" + info "Valid: (${INTERFACE})." else error_exit "Invalid: (${INTERFACE})." fi @@ -248,12 +248,12 @@ create_jail() { ## MAKE SURE WE'RE IN THE RIGHT PLACE cd "${bastille_jail_path}" echo - echo -e "${COLOR_GREEN}NAME: ${NAME}.${COLOR_RESET}" - echo -e "${COLOR_GREEN}IP: ${IP}.${COLOR_RESET}" + info "NAME: ${NAME}." + info "IP: ${IP}." if [ -n "${INTERFACE}" ]; then - echo -e "${COLOR_GREEN}INTERFACE: ${INTERFACE}.${COLOR_RESET}" + info "INTERFACE: ${INTERFACE}." fi - echo -e "${COLOR_GREEN}RELEASE: ${RELEASE}.${COLOR_RESET}" + info "RELEASE: ${RELEASE}." echo if [ -z "${THICK_JAIL}" ]; then @@ -278,7 +278,7 @@ create_jail() { fi done else - echo -e "${COLOR_GREEN}Creating a thickjail, this may take a while...${COLOR_RESET}" + info "Creating a thickjail. This may take a while..." if [ "${bastille_zfs_enable}" = "YES" ]; then if [ -n "${bastille_zfs_zpool}" ]; then ## perform release base replication @@ -527,7 +527,7 @@ if [ -z "${EMPTY_JAIL}" ]; then validate_netconf fi else - echo -e "${COLOR_GREEN}Creating empty jail: ${NAME}.${COLOR_RESET}" + info "Creating empty jail: ${NAME}." fi ## check if a running jail matches name or already exist diff --git a/usr/local/share/bastille/destroy.sh b/usr/local/share/bastille/destroy.sh index fb28e360..a4bb3c57 100644 --- a/usr/local/share/bastille/destroy.sh +++ b/usr/local/share/bastille/destroy.sh @@ -54,7 +54,7 @@ destroy_jail() { fi if [ -d "${bastille_jail_base}" ]; then - echo -e "${COLOR_GREEN}Deleting Jail: ${TARGET}.${COLOR_RESET}" + info "Deleting Jail: ${TARGET}." if [ "${bastille_zfs_enable}" = "YES" ]; then if [ -n "${bastille_zfs_zpool}" ]; then if [ -n "${TARGET}" ]; then @@ -79,13 +79,13 @@ destroy_jail() { ## archive jail log if [ -f "${bastille_jail_log}" ]; then mv "${bastille_jail_log}" "${bastille_jail_log}"-"$(date +%F)" - echo -e "${COLOR_GREEN}Note: jail console logs archived.${COLOR_RESET}" - echo -e "${COLOR_GREEN}${bastille_jail_log}-$(date +%F)${COLOR_RESET}" + info "Note: jail console logs archived." + info "${bastille_jail_log}-$(date +%F)" fi ## clear any active rdr rules if [ ! -z "$(pfctl -a "rdr/${TARGET}" -Psn 2>/dev/null)" ]; then - echo -e "${COLOR_GREEN}Clearing RDR rules:${COLOR_RESET}" + info "Clearing RDR rules:" pfctl -a "rdr/${TARGET}" -Fn fi echo @@ -120,7 +120,7 @@ destroy_rel() { error_exit "Release base not found." else if [ "${BASE_HASCHILD}" -eq "0" ]; then - echo -e "${COLOR_GREEN}Deleting base: ${TARGET}.${COLOR_RESET}" + info "Deleting base: ${TARGET}" if [ "${bastille_zfs_enable}" = "YES" ]; then if [ -n "${bastille_zfs_zpool}" ]; then if [ -n "${TARGET}" ]; then diff --git a/usr/local/share/bastille/export.sh b/usr/local/share/bastille/export.sh index 09256b12..e2773376 100644 --- a/usr/local/share/bastille/export.sh +++ b/usr/local/share/bastille/export.sh @@ -90,8 +90,8 @@ jail_export() if [ "${bastille_zfs_enable}" = "YES" ]; then if [ -n "${bastille_zfs_zpool}" ]; then FILE_EXT="xz" - echo -e "${COLOR_GREEN}Exporting '${TARGET}' to a compressed .${FILE_EXT} archive.${COLOR_RESET}" - echo -e "${COLOR_GREEN}Sending zfs data stream...${COLOR_RESET}" + info "Exporting '${TARGET}' to a compressed .${FILE_EXT} archive." + info "Sending zfs data stream..." # Take a recursive temporary snapshot zfs snapshot -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" @@ -104,7 +104,7 @@ jail_export() else # Create standard backup archive FILE_EXT="txz" - echo -e "${COLOR_GREEN}Exporting '${TARGET}' to a compressed .${FILE_EXT} archive...${COLOR_RESET}" + info "Exporting '${TARGET}' to a compressed .${FILE_EXT} archive..." cd "${bastille_jailsdir}" && tar -cf - "${TARGET}" | xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}.${FILE_EXT}" fi @@ -114,7 +114,7 @@ jail_export() # Generate container checksum file cd "${bastille_backupsdir}" sha256 -q "${TARGET}_${DATE}.${FILE_EXT}" > "${TARGET}_${DATE}.sha256" - echo -e "${COLOR_GREEN}Exported '${bastille_backupsdir}/${TARGET}_${DATE}.${FILE_EXT}' successfully.${COLOR_RESET}" + info "Exported '${bastille_backupsdir}/${TARGET}_${DATE}.${FILE_EXT}' successfully." exit 0 fi } diff --git a/usr/local/share/bastille/htop.sh b/usr/local/share/bastille/htop.sh index 6f1bdf20..df792eea 100644 --- a/usr/local/share/bastille/htop.sh +++ b/usr/local/share/bastille/htop.sh @@ -51,7 +51,7 @@ for _jail in ${JAILS}; do if [ ! -x "${bastille_jail_path}/usr/local/bin/htop" ]; then error_notify "htop not found on ${_jail}." elif [ -x "${bastille_jail_path}/usr/local/bin/htop" ]; then - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" jexec -l ${_jail} /usr/local/bin/htop fi echo -e "${COLOR_RESET}" diff --git a/usr/local/share/bastille/import.sh b/usr/local/share/bastille/import.sh index eecad9f1..5ac259f3 100644 --- a/usr/local/share/bastille/import.sh +++ b/usr/local/share/bastille/import.sh @@ -56,25 +56,25 @@ validate_archive() { if [ "${FILE_EXT}" != ".tar.gz" ] && [ "${FILE_EXT}" != ".tar" ]; then if [ -f "${bastille_backupsdir}/${TARGET}" ]; then if [ -f "${bastille_backupsdir}/${FILE_TRIM}.sha256" ]; then - echo -e "${COLOR_GREEN}Validating file: ${TARGET}...${COLOR_RESET}" + info "Validating 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}." else - echo -e "${COLOR_GREEN}File validation successful!${COLOR_RESET}" + info "File validation successful!" fi else # Check if user opt to force import if [ "${OPTION}" = "-f" -o "${OPTION}" = "force" ]; then - echo -e "${COLOR_YELLOW}Warning: Skipping archive validation!${COLOR_RESET}" + warn "Warning: Skipping archive validation!" else error_exit "Checksum file not found. See 'bastille import TARGET -f'." fi fi fi else - echo -e "${COLOR_YELLOW}Warning: Skipping archive validation!${COLOR_RESET}" + warn "Warning: Skipping archive validation!" fi } @@ -83,7 +83,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 - echo -e "${COLOR_GREEN}Updating zfs mountpoint...${COLOR_RESET}" + info "Updating ZFS mountpoint..." zfs set mountpoint="${bastille_jailsdir}/${TARGET_TRIM}/root" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" fi @@ -101,7 +101,7 @@ update_jailconf() { 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 - echo -e "${COLOR_GREEN}Updating jail.conf...${COLOR_RESET}" + info "Updating 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}" @@ -119,7 +119,7 @@ update_fstab() { 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 - echo -e "${COLOR_GREEN}Updating fstab...${COLOR_RESET}" + info "Updating fstab..." sed -i '' "s|${FSTAB_CURRENT}|${FSTAB_NEWCONF}|" "${FSTAB_CONFIG}" fi fi @@ -128,7 +128,7 @@ update_fstab() { 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 - echo -e "${COLOR_GREEN}Generating jail.conf...${COLOR_RESET}" + info "Generating jail.conf..." if [ "${FILE_EXT}" = ".zip" ]; then # Gather some bits from foreign/iocage config files @@ -188,7 +188,7 @@ generate_config() { IPX_ADDR="ip4.addr" IP_CONFIG="-" IP6_MODE="disable" - echo -e "${COLOR_YELLOW}Warning: See 'bastille edit ${TARGET_TRIM} jail.conf' for manual network configuration${COLOR_RESET}" + warn "Warning: See 'bastille edit ${TARGET_TRIM} jail.conf' for manual network configuration." fi if [ "${FILE_EXT}" = ".tar.gz" ]; then @@ -196,7 +196,7 @@ generate_config() { if [ -z "${CONFIG_RELEASE}" ]; then # Fallback to host version CONFIG_RELEASE=$(freebsd-version | sed 's/\-[pP].*//') - echo -e "${COLOR_YELLOW}Warning: ${CONFIG_RELEASE} was set by default!${COLOR_RESET}" + 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" \ @@ -241,7 +241,7 @@ update_config() { if [ -z "${CONFIG_RELEASE}" ]; then # Fallback to host version CONFIG_RELEASE=$(freebsd-version | sed 's/\-[pP].*//') - echo -e "${COLOR_YELLOW}Warning: ${CONFIG_RELEASE} was set by default!${COLOR_RESET}" + 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" \ @@ -282,11 +282,11 @@ update_symlinks() { # Just warn user to bootstrap the release if missing if [ ! -d "${bastille_releasesdir}/${CONFIG_RELEASE}" ]; then - echo -e "${COLOR_YELLOW}Warning: ${CONFIG_RELEASE} must be bootstrapped, See 'bastille bootstrap'.${COLOR_RESET}" + warn "Warning: ${CONFIG_RELEASE} must be bootstrapped. See 'bastille bootstrap'." fi # Update old symlinks - echo -e "${COLOR_GREEN}Updating symlinks...${COLOR_RESET}" + info "Updating symlinks..." for _link in ${SYMLINKS}; do if [ -L "${_link}" ]; then ln -sf /.bastille/${_link} ${_link} @@ -296,8 +296,8 @@ update_symlinks() { create_zfs_datasets() { # Prepare the ZFS environment and restore from file - echo -e "${COLOR_GREEN}Importing '${TARGET_TRIM}' from foreign compressed ${FILE_EXT} archive.${COLOR_RESET}" - echo -e "${COLOR_GREEN}Preparing zfs environment...${COLOR_RESET}" + info "Importing '${TARGET_TRIM}' from foreign compressed ${FILE_EXT} archive." + info "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}" @@ -321,8 +321,8 @@ jail_import() { if [ -n "${bastille_zfs_zpool}" ]; then if [ "${FILE_EXT}" = ".xz" ]; then # Import from compressed xz on ZFS systems - echo -e "${COLOR_GREEN}Importing '${TARGET_TRIM}' from compressed ${FILE_EXT} archive.${COLOR_RESET}" - echo -e "${COLOR_GREEN}Receiving zfs data stream...${COLOR_RESET}" + info "Importing '${TARGET_TRIM}' from compressed ${FILE_EXT} archive." + info "Receiving ZFS data stream..." xz ${bastille_decompress_xz_options} "${bastille_backupsdir}/${TARGET}" | \ zfs receive -u "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" @@ -334,7 +334,7 @@ jail_import() { create_zfs_datasets # Extract required files to the new datasets - echo -e "${COLOR_GREEN}Extracting files from '${TARGET}' archive...${COLOR_RESET}" + info "Extracting 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 @@ -342,7 +342,7 @@ jail_import() { fi elif [ "${FILE_EXT}" = ".zip" ]; then # Attempt to import a foreign/iocage container - echo -e "${COLOR_GREEN}Importing '${TARGET_TRIM}' from foreign compressed ${FILE_EXT} archive.${COLOR_RESET}" + info "Importing '${TARGET_TRIM}' from foreign compressed ${FILE_EXT} archive." # Sane bastille zfs options ZFS_OPTIONS=$(echo ${bastille_zfs_options} | sed 's/-o//g') @@ -352,7 +352,7 @@ jail_import() { error_exit "Failed to extract files from '${TARGET}' archive." rm -f "${FILE_TRIM}" "${FILE_TRIM}_root" fi - echo -e "${COLOR_GREEN}Receiving zfs data stream...${COLOR_RESET}" + info "Receiving ZFS data stream..." zfs receive -u "${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 -u "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" < "${FILE_TRIM}_root" @@ -376,7 +376,7 @@ jail_import() { create_zfs_datasets # Extract required files to the new datasets - echo -e "${COLOR_GREEN}Extracting files from '${TARGET}' archive...${COLOR_RESET}" + info "Extracting 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 @@ -391,7 +391,7 @@ jail_import() { workout_components # Extract required files to the new datasets - echo -e "${COLOR_GREEN}Extracting files from '${TARGET}' archive...${COLOR_RESET}" + info "Extracting 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 @@ -410,18 +410,18 @@ jail_import() { else # Import from standard supported archives on UFS systems if [ "${FILE_EXT}" = ".txz" ]; then - echo -e "${COLOR_GREEN}Extracting files from '${TARGET}' archive...${COLOR_RESET}" + info "Extracting files from '${TARGET}' archive..." tar -Jxf "${bastille_backupsdir}/${TARGET}" -C "${bastille_jailsdir}" elif [ "${FILE_EXT}" = ".tar.gz" ]; then # Attempt to import/configure foreign/ezjail container - echo -e "${COLOR_GREEN}Extracting files from '${TARGET}' archive...${COLOR_RESET}" + info "Extracting 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 - echo -e "${COLOR_GREEN}Extracting files from '${TARGET}' archive...${COLOR_RESET}" + info "Extracting 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}" @@ -442,7 +442,7 @@ jail_import() { # This is required on foreign imports only update_jailconf update_fstab - echo -e "${COLOR_GREEN}Container '${TARGET_TRIM}' imported successfully.${COLOR_RESET}" + info "Container '${TARGET_TRIM}' imported successfully." exit 0 fi else diff --git a/usr/local/share/bastille/limits.sh b/usr/local/share/bastille/limits.sh index 1d4de5cb..ca48427d 100644 --- a/usr/local/share/bastille/limits.sh +++ b/usr/local/share/bastille/limits.sh @@ -59,7 +59,7 @@ OPTION="${1}" VALUE="${2}" for _jail in ${JAILS}; do - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" _rctl_rule="jail:${_jail}:${OPTION}:deny=${VALUE}/jail" diff --git a/usr/local/share/bastille/mount.sh b/usr/local/share/bastille/mount.sh index 21173ab7..fc37b1e5 100644 --- a/usr/local/share/bastille/mount.sh +++ b/usr/local/share/bastille/mount.sh @@ -60,37 +60,37 @@ _checks=$(echo "${_fstab}" | awk '{print $5" "$6}') ## if any variables are empty, bail out if [ -z "${_hostpath}" ] || [ -z "${_jailpath}" ] || [ -z "${_type}" ] || [ -z "${_perms}" ] || [ -z "${_checks}" ]; then error_notify "FSTAB format not recognized." - echo -e "${COLOR_YELLOW}Format: /host/path jail/path nullfs ro 0 0${COLOR_RESET}" - echo -e "${COLOR_YELLOW}Read: ${_fstab}${COLOR_RESET}" + warn "Format: /host/path jail/path nullfs ro 0 0" + warn "Read: ${_fstab}" exit 1 fi ## if host path doesn't exist or type is not "nullfs" if [ ! -d "${_hostpath}" ] || [ "${_type}" != "nullfs" ]; then error_notify "Detected invalid host path or incorrect mount type in FSTAB." - echo -e "${COLOR_YELLOW}Format: /host/path jail/path nullfs ro 0 0${COLOR_RESET}" - echo -e "${COLOR_YELLOW}Read: ${_fstab}${COLOR_RESET}" + warn "Format: /host/path jail/path nullfs ro 0 0" + warn "Read: ${_fstab}" exit 1 fi ## if mount permissions are not "ro" or "rw" if [ "${_perms}" != "ro" ] && [ "${_perms}" != "rw" ]; then error_notify "Detected invalid mount permissions in FSTAB." - echo -e "${COLOR_YELLOW}Format: /host/path jail/path nullfs ro 0 0${COLOR_RESET}" - echo -e "${COLOR_YELLOW}Read: ${_fstab}${COLOR_RESET}" + warn "Format: /host/path jail/path nullfs ro 0 0" + warn "Read: ${_fstab}" exit 1 fi ## if check & pass are not "0 0 - 1 1"; bail out if [ "${_checks}" != "0 0" ] && [ "${_checks}" != "1 0" ] && [ "${_checks}" != "0 1" ] && [ "${_checks}" != "1 1" ]; then error_notify "Detected invalid fstab options in FSTAB." - echo -e "${COLOR_YELLOW}Format: /host/path jail/path nullfs ro 0 0${COLOR_RESET}" - echo -e "${COLOR_YELLOW}Read: ${_fstab}${COLOR_RESET}" + warn "Format: /host/path jail/path nullfs ro 0 0" + warn "Read: ${_fstab}" exit 1 fi for _jail in ${JAILS}; do - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" ## aggregate variables into FSTAB entry _jailpath="${bastille_jailsdir}/${_jail}/root/${_jailpath}" diff --git a/usr/local/share/bastille/pkg.sh b/usr/local/share/bastille/pkg.sh index d3f7181c..715b6438 100644 --- a/usr/local/share/bastille/pkg.sh +++ b/usr/local/share/bastille/pkg.sh @@ -46,7 +46,7 @@ if [ $# -lt 1 ]; then fi for _jail in ${JAILS}; do - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" jexec -l "${_jail}" /usr/sbin/pkg "$@" echo done diff --git a/usr/local/share/bastille/rename.sh b/usr/local/share/bastille/rename.sh index 14541fb2..94fca660 100644 --- a/usr/local/share/bastille/rename.sh +++ b/usr/local/share/bastille/rename.sh @@ -88,7 +88,7 @@ update_fstab() { change_name() { # Attempt container name change - echo -e "${COLOR_GREEN}Attempting to rename '${TARGET}' to ${NEWNAME}...${COLOR_RESET}" + info "Attempting to rename '${TARGET}' to ${NEWNAME}..." if [ "${bastille_zfs_enable}" = "YES" ]; then if [ -n "${bastille_zfs_zpool}" ] && [ -n "${bastille_zfs_prefix}" ]; then # Check and rename container ZFS dataset accordingly @@ -131,7 +131,7 @@ change_name() { if [ "$?" -ne 0 ]; then error_exit "An error has occurred while attempting to rename '${TARGET}'." else - echo -e "${COLOR_GREEN}Renamed '${TARGET}' to '${NEWNAME}' successfully.${COLOR_RESET}" + info "Renamed '${TARGET}' to '${NEWNAME}' successfully." fi } diff --git a/usr/local/share/bastille/service.sh b/usr/local/share/bastille/service.sh index b90b881b..9ef37a72 100644 --- a/usr/local/share/bastille/service.sh +++ b/usr/local/share/bastille/service.sh @@ -46,7 +46,7 @@ if [ $# -ne 2 ]; then fi for _jail in ${JAILS}; do - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" jexec -l "${_jail}" /usr/sbin/service "$@" echo done diff --git a/usr/local/share/bastille/start.sh b/usr/local/share/bastille/start.sh index 47f135a8..145c7be5 100644 --- a/usr/local/share/bastille/start.sh +++ b/usr/local/share/bastille/start.sh @@ -76,7 +76,7 @@ for _jail in ${JAILS}; do fi ## start the container - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" jail -f "${bastille_jailsdir}/${_jail}/jail.conf" -c "${_jail}" ## add rctl limits diff --git a/usr/local/share/bastille/stop.sh b/usr/local/share/bastille/stop.sh index 21e84931..1aac57e2 100644 --- a/usr/local/share/bastille/stop.sh +++ b/usr/local/share/bastille/stop.sh @@ -64,7 +64,7 @@ for _jail in ${JAILS}; do fi ## stop container - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" jail -f "${bastille_jailsdir}/${_jail}/jail.conf" -r "${_jail}" fi echo diff --git a/usr/local/share/bastille/sysrc.sh b/usr/local/share/bastille/sysrc.sh index 2ab807d1..eb368ee3 100644 --- a/usr/local/share/bastille/sysrc.sh +++ b/usr/local/share/bastille/sysrc.sh @@ -46,7 +46,7 @@ if [ $# -lt 1 ]; then fi for _jail in ${JAILS}; do - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" jexec -l "${_jail}" /usr/sbin/sysrc "$@" echo -e "${COLOR_RESET}" done diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 8ec25ca8..2f1e7a7e 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -101,7 +101,7 @@ render() { elif [ -f "${_file_path}" ]; then eval "sed -i '' ${ARG_REPLACEMENTS} '${_file_path}'" else - echo -e "${COLOR_YELLOW}Path not found for render: ${2}${COLOR_RESET}" + warn "Path not found for render: ${2}" fi } @@ -122,7 +122,7 @@ case ${TEMPLATE} in http?://github.com/*/*|http?://gitlab.com/*/*) TEMPLATE_DIR=$(echo "${TEMPLATE}" | awk -F / '{ print $4 "/" $5 }') if [ ! -d "${bastille_templatesdir}/${TEMPLATE_DIR}" ]; then - echo -e "${COLOR_GREEN}Bootstrapping ${TEMPLATE}...${COLOR_RESET}" + info "Bootstrapping ${TEMPLATE}..." if ! bastille bootstrap "${TEMPLATE}"; then error_exit "Failed to bootstrap template: ${TEMPLATE}" fi @@ -172,18 +172,18 @@ for _jail in ${JAILS}; do ## jail-specific variables. bastille_jail_path=$(jls -j "${_jail}" path) - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" - echo -e "${COLOR_GREEN}Applying template: ${TEMPLATE}...${COLOR_RESET}" + info "[${_jail}]:" + info "Applying template: ${TEMPLATE}..." ## TARGET if [ -s "${bastille_template}/TARGET" ]; then if grep -qw "${_jail}" "${bastille_template}/TARGET"; then - echo -e "${COLOR_GREEN}TARGET: !${_jail}.${COLOR_RESET}" + info "TARGET: !${_jail}." echo continue fi if ! grep -Eq "(^|\b)(${_jail}|ALL)($|\b)" "${bastille_template}/TARGET"; then - echo -e "${COLOR_GREEN}TARGET: ?${_jail}.${COLOR_RESET}" + info "TARGET: ?${_jail}." echo continue fi @@ -199,7 +199,7 @@ for _jail in ${JAILS}; do _arg_name=$(get_arg_name "${_line}") _arg_value=$(get_arg_value "${_line}" "$@") if [ -z "${_arg_value}" ]; then - echo -e "${COLOR_YELLOW}No value provided for arg: ${_arg_name}${COLOR_RESET}" + warn "No value provided for arg: ${_arg_name}" fi # Build a list of sed commands like this: -e 's/${username}/root/g' -e 's/${domain}/example.com/g' ARG_REPLACEMENTS="${ARG_REPLACEMENTS} -e 's/\${${_arg_name}}/${_arg_value}/g'" @@ -225,7 +225,7 @@ for _jail in ${JAILS}; do _arg_name=$(get_arg_name "${_args}") _arg_value=$(get_arg_value "${_args}" "$@") if [ -z "${_arg_value}" ]; then - echo -e "${COLOR_YELLOW}No value provided for arg: ${_arg_name}${COLOR_RESET}" + warn "No value provided for arg: ${_arg_name}" fi # Build a list of sed commands like this: -e 's/${username}/root/g' -e 's/${domain}/example.com/g' ARG_REPLACEMENTS="${ARG_REPLACEMENTS} -e 's/\${${_arg_name}}/${_arg_value}/g'" @@ -279,7 +279,7 @@ for _jail in ${JAILS}; do # Override default command/args for some hooks. -- cwells case ${_hook} in CONFIG) - echo -e "${COLOR_YELLOW}CONFIG deprecated; rename to OVERLAY.${COLOR_RESET}" + warn "CONFIG deprecated; rename to OVERLAY." _args_template='${bastille_template}/${_line} /' _cmd='cp' ;; FSTAB) @@ -290,7 +290,7 @@ for _jail in ${JAILS}; do _args_template='${bastille_template}/${_line} /' _cmd='cp' ;; PF) - echo -e "${COLOR_GREEN}NOT YET IMPLEMENTED.${COLOR_RESET}" + info "NOT YET IMPLEMENTED." continue ;; PRE) _cmd='cmd' ;; @@ -300,7 +300,7 @@ for _jail in ${JAILS}; do ;; esac - echo -e "${COLOR_GREEN}[${_jail}]:${_hook} -- START${COLOR_RESET}" + info "[${_jail}]:${_hook} -- START" if [ "${_hook}" = 'CMD' ] || [ "${_hook}" = 'PRE' ]; then bastille cmd "${_jail}" /bin/sh < "${bastille_template}/${_hook}" || exit 1 elif [ "${_hook}" = 'PKG' ]; then @@ -317,11 +317,11 @@ for _jail in ${JAILS}; do bastille "${_cmd}" "${_jail}" ${_args} || exit 1 done < "${bastille_template}/${_hook}" fi - echo -e "${COLOR_GREEN}[${_jail}]:${_hook} -- END${COLOR_RESET}" + info "[${_jail}]:${_hook} -- END" echo fi done - echo -e "${COLOR_GREEN}Template complete.${COLOR_RESET}" + info "Template complete." echo done diff --git a/usr/local/share/bastille/top.sh b/usr/local/share/bastille/top.sh index 5f248653..05e23953 100644 --- a/usr/local/share/bastille/top.sh +++ b/usr/local/share/bastille/top.sh @@ -46,7 +46,7 @@ if [ $# -ne 0 ]; then fi for _jail in ${JAILS}; do - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" jexec -l "${_jail}" /usr/bin/top echo -e "${COLOR_RESET}" done diff --git a/usr/local/share/bastille/umount.sh b/usr/local/share/bastille/umount.sh index 0b1894d2..518461b0 100644 --- a/usr/local/share/bastille/umount.sh +++ b/usr/local/share/bastille/umount.sh @@ -49,7 +49,7 @@ fi MOUNT_PATH=$1 for _jail in ${JAILS}; do - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" _jailpath="${bastille_jailsdir}/${_jail}/root/${MOUNT_PATH}" diff --git a/usr/local/share/bastille/verify.sh b/usr/local/share/bastille/verify.sh index 13479a50..7239e252 100644 --- a/usr/local/share/bastille/verify.sh +++ b/usr/local/share/bastille/verify.sh @@ -55,22 +55,22 @@ verify_template() { _path=${_template_path}/${_hook} if [ -s "${_path}" ]; then _hook_validate=$((_hook_validate+1)) - echo -e "${COLOR_GREEN}Detected ${_hook} hook.${COLOR_RESET}" + info "Detected ${_hook} hook." ## line count must match newline count if [ $(wc -l "${_path}" | awk '{print $1}') -ne $(grep -c $'\n' "${_path}") ]; then - echo -e "${COLOR_GREEN}[${_hook}]:${COLOR_RESET}" + 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 - echo -e "${COLOR_GREEN}[${_hook}]:${COLOR_RESET}" + info "[${_hook}]:" cat "${_path}" echo while read _include; do - echo -e "${COLOR_GREEN}[${_hook}]:[${_include}]:${COLOR_RESET}" + info "[${_hook}]:[${_include}]:" case ${_include} in http?://github.com/*/*|http?://gitlab.com/*/*) @@ -89,11 +89,11 @@ verify_template() { ## if tree; tree -a bastille_template/_dir elif [ ${_hook} = 'OVERLAY' ]; then - echo -e "${COLOR_GREEN}[${_hook}]:${COLOR_RESET}" + info "[${_hook}]:" cat "${_path}" echo while read _dir; do - echo -e "${COLOR_GREEN}[${_hook}]:[${_dir}]:${COLOR_RESET}" + info "[${_hook}]:[${_dir}]:" if [ -x /usr/local/bin/tree ]; then /usr/local/bin/tree -a "${_template_path}/${_dir}" else @@ -102,7 +102,7 @@ verify_template() { echo done < "${_path}" else - echo -e "${COLOR_GREEN}[${_hook}]:${COLOR_RESET}" + info "[${_hook}]:" cat "${_path}" echo fi @@ -119,7 +119,7 @@ verify_template() { ## if validated; ready to use if [ ${_hook_validate} -gt 0 ]; then - echo -e "${COLOR_GREEN}Template ready to use.${COLOR_RESET}" + info "Template ready to use." fi } diff --git a/usr/local/share/bastille/zfs.sh b/usr/local/share/bastille/zfs.sh index 0f34f328..da4f065d 100644 --- a/usr/local/share/bastille/zfs.sh +++ b/usr/local/share/bastille/zfs.sh @@ -37,7 +37,7 @@ usage() { zfs_snapshot() { for _jail in ${JAILS}; do - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" zfs snapshot -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}"@"${TAG}" echo done @@ -45,7 +45,7 @@ done zfs_set_value() { for _jail in ${JAILS}; do - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" zfs "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" echo done @@ -53,7 +53,7 @@ done zfs_get_value() { for _jail in ${JAILS}; do - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" zfs get "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" echo done @@ -61,7 +61,7 @@ done zfs_disk_usage() { for _jail in ${JAILS}; do - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + info "[${_jail}]:" zfs list -t all -o name,used,avail,refer,mountpoint,compress,ratio -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" echo done From 64b869e295dbdd8bf6189c423365c5be01d39999 Mon Sep 17 00:00:00 2001 From: Tobias Tom Date: Fri, 27 Nov 2020 12:01:05 +0000 Subject: [PATCH 03/26] Clarified the `RENDER` functionality. --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4eab2a75..0ca7694a 100644 --- a/README.md +++ b/README.md @@ -678,9 +678,10 @@ Note: SYSRC requires NO quotes or that quotes (`"`) be escaped. ie; `\"`) Any name provided in the ARG file can be used as a variable in the other hooks. For example, `name=value` in the ARG file will cause instances of `${name}` -to be replaced with `value`. The `RENDER` hook can be used to specify files or -directories whose contents should have the variables replaced. Values can be specified -either through the command line when applying the template or as a default in the ARG file. +to be replaced with `value`. The `RENDER` hook can be used to specify existing files or +directories inside the jail whose contents should have the variables replaced. Values can be +specified either through the command line when applying the template or as a default in the ARG +file. In addition to supporting template hooks, Bastille supports overlaying files into the container. This is done by placing the files in their full path, using the From 5e9578ca5e531d473fe260f519014d39dc648aab Mon Sep 17 00:00:00 2001 From: Chris Wells Date: Fri, 27 Nov 2020 19:20:47 -0500 Subject: [PATCH 04/26] Use uppercase ZFS when appropriate. --- README.md | 10 +++++----- docs/chapters/usage.rst | 2 +- usr/local/bin/bastille | 2 +- usr/local/share/bastille/export.sh | 2 +- usr/local/share/bastille/import.sh | 4 ++-- usr/local/share/bastille/rename.sh | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 0ca7694a..1f4d78ae 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Available Commands: update Update container base -pX release. upgrade Upgrade container release to X.Y-RELEASE. verify Verify bootstrapped release or automation template. - zfs Manage (get|set) zfs attributes on targeted container(s). + zfs Manage (get|set) ZFS attributes on targeted container(s). Use "bastille -v|--version" for version information. Use "bastille command -h|--help" for more information about a command. @@ -679,7 +679,7 @@ Note: SYSRC requires NO quotes or that quotes (`"`) be escaped. ie; `\"`) Any name provided in the ARG file can be used as a variable in the other hooks. For example, `name=value` in the ARG file will cause instances of `${name}` to be replaced with `value`. The `RENDER` hook can be used to specify existing files or -directories inside the jail whose contents should have the variables replaced. Values can be +directories inside the jail whose contents should have the variables replaced. Values can be specified either through the command line when applying the template or as a default in the ARG file. @@ -935,7 +935,7 @@ validation are not used. bastille zfs ------------ -This sub-command allows managing zfs attributes for the targeted container(s). +This sub-command allows managing ZFS attributes for the targeted container(s). Common usage includes setting container quotas. **set quota** @@ -961,7 +961,7 @@ Note: On UFS systems containers must be stopped before export. ```shell ishmael ~ # bastille export folsom Exporting 'folsom' to a compressed .xz archive. -Sending zfs data stream... +Sending ZFS data stream... 100 % 1057.2 KiB / 9231.5 KiB = 0.115 0:01 Exported '/usr/local/bastille/jails/backups/folsom_2020-01-26-19:23:04.xz' successfully. @@ -976,7 +976,7 @@ ishmael ~ # bastille import folsom_2020-01-26-19:22:23.xz Validating file: folsom_2020-01-26-19:22:23.xz... File validation successful! Importing 'folsom' from compressed .xz archive. -Receiving zfs data stream... +Receiving ZFS data stream... /usr/local/bastille/jails/backups/folsom_2020-01-26-19:22:23.xz (1/1) 100 % 626.4 KiB / 9231.5 KiB = 0.068 0:02 Container 'folsom' imported successfully. diff --git a/docs/chapters/usage.rst b/docs/chapters/usage.rst index e6f4f78a..b4d9ef48 100644 --- a/docs/chapters/usage.rst +++ b/docs/chapters/usage.rst @@ -40,7 +40,7 @@ Usage update Update container base -pX release. upgrade Upgrade container release to X.Y-RELEASE. verify Compare release against a "known good" index. - zfs Manage (get|set) zfs attributes on targeted container(s). + zfs Manage (get|set) ZFS attributes on targeted container(s). Use "bastille -v|--version" for version information. Use "bastille command -h|--help" for more information about a command. diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index b984f342..42b4fedb 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -110,7 +110,7 @@ Available Commands: update Update container base -pX release. upgrade Upgrade container release to X.Y-RELEASE. verify Compare release against a "known good" index. - zfs Manage (get|set) zfs attributes on targeted container(s). + zfs Manage (get|set) ZFS attributes on targeted container(s). Use "bastille -v|--version" for version information. Use "bastille command -h|--help" for more information about a command. diff --git a/usr/local/share/bastille/export.sh b/usr/local/share/bastille/export.sh index e2773376..398c1632 100644 --- a/usr/local/share/bastille/export.sh +++ b/usr/local/share/bastille/export.sh @@ -91,7 +91,7 @@ jail_export() if [ -n "${bastille_zfs_zpool}" ]; then FILE_EXT="xz" info "Exporting '${TARGET}' to a compressed .${FILE_EXT} archive." - info "Sending zfs data stream..." + info "Sending ZFS data stream..." # Take a recursive temporary snapshot zfs snapshot -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" diff --git a/usr/local/share/bastille/import.sh b/usr/local/share/bastille/import.sh index 5ac259f3..75d50268 100644 --- a/usr/local/share/bastille/import.sh +++ b/usr/local/share/bastille/import.sh @@ -79,7 +79,7 @@ validate_archive() { } update_zfsmount() { - # Update the mountpoint property on the received zfs data stream + # Update the mountpoint property on the received ZFS data stream 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 @@ -343,7 +343,7 @@ jail_import() { elif [ "${FILE_EXT}" = ".zip" ]; then # Attempt to import a foreign/iocage container info "Importing '${TARGET_TRIM}' from foreign compressed ${FILE_EXT} archive." - # Sane bastille zfs options + # Sane bastille ZFS options ZFS_OPTIONS=$(echo ${bastille_zfs_options} | sed 's/-o//g') # Extract required files from the zip archive diff --git a/usr/local/share/bastille/rename.sh b/usr/local/share/bastille/rename.sh index 94fca660..1fb73d2a 100644 --- a/usr/local/share/bastille/rename.sh +++ b/usr/local/share/bastille/rename.sh @@ -92,7 +92,7 @@ change_name() { if [ "${bastille_zfs_enable}" = "YES" ]; then if [ -n "${bastille_zfs_zpool}" ] && [ -n "${bastille_zfs_prefix}" ]; then # Check and rename container ZFS dataset accordingly - # Perform additional checks in case of non-zfs existing containers + # Perform additional checks in case of non-ZFS existing containers if zfs list | grep -qw "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}"; then if ! zfs rename -f "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NEWNAME}"; then error_exit "Can't rename '${TARGET}' dataset." @@ -115,7 +115,7 @@ change_name() { error_exit "Can't rename '${TARGET}' dataset." fi else - error_exit "Can't determine the zfs origin path of '${TARGET}'." + error_exit "Can't determine the ZFS origin path of '${TARGET}'." fi else # Just rename the jail directory From 4c9f1aca25e5647146ba5238d3bf72f6ffe1e7a6 Mon Sep 17 00:00:00 2001 From: Chris Wells Date: Sat, 28 Nov 2020 12:09:56 -0500 Subject: [PATCH 05/26] Add 'config' command to get/set jail config properties. --- README.md | 1 + usr/local/bin/bastille | 3 +- usr/local/share/bastille/config.sh | 113 +++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 usr/local/share/bastille/config.sh diff --git a/README.md b/README.md index 0ca7694a..d0711469 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ Available Commands: bootstrap Bootstrap a FreeBSD release for container base. clone Clone an existing container. cmd Execute arbitrary command on targeted container(s). + config Get or set a config value for the targeted container(s). console Console into a running container. convert Convert a thin container into a thick container. cp cp(1) files from host to targeted container(s). diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index b984f342..40a7929a 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -84,6 +84,7 @@ Available Commands: bootstrap Bootstrap a FreeBSD release for container base. cmd Execute arbitrary command on targeted container(s). clone Clone an existing container. + config Get or set a config value for the targeted container(s). console Console into a running container. convert Convert a Thin container into a Thick container. cp cp(1) files from host to targeted container(s). @@ -136,7 +137,7 @@ help|-h|--help) bootstrap|create|destroy|import|list|rdr|restart|start|update|upgrade|verify) # Nothing "extra" to do for these commands. -- cwells ;; -clone|cmd|console|convert|cp|edit|export|htop|limits|mount|pkg|rename|service|stop|sysrc|template|top|umount|zfs) +clone|config|cmd|console|convert|cp|edit|export|htop|limits|mount|pkg|rename|service|stop|sysrc|template|top|umount|zfs) # Parse the target and ensure it exists. -- cwells if [ $# -eq 0 ]; then # No target was given, so show the command's help. -- cwells PARAMS='help' diff --git a/usr/local/share/bastille/config.sh b/usr/local/share/bastille/config.sh new file mode 100644 index 00000000..b40835b5 --- /dev/null +++ b/usr/local/share/bastille/config.sh @@ -0,0 +1,113 @@ +#!/bin/sh +# +# Copyright (c) 2018-2020, Christer Edwards +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +. /usr/local/share/bastille/common.sh +. /usr/local/etc/bastille/bastille.conf + +usage() { + error_exit "Usage: bastille config TARGET get|set propertyName [newValue]" +} + +# Handle special-case commands first. +case "$1" in +help|-h|--help) + usage + ;; +esac + +if [ $# -eq 1 ] || [ $# -gt 3 ]; then + usage +fi + +ACTION=$1 +shift + +case $ACTION in + get) + if [ $# -ne 1 ]; then + error_notify 'Too many parameters for a "get" operation.' + usage + fi + ;; + set) ;; + *) error_exit 'Only get and set are supported.' ;; +esac + +PROPERTY=$1 +shift +VALUE="$@" + +for _jail in ${JAILS}; do + FILE="${bastille_jailsdir}/${_jail}/jail.conf" + if [ ! -f "${FILE}" ]; then + error_notify "jail.conf does not exist for jail: ${_jail}" + continue + fi + + MATCH_LINE=$(grep "^\s*${PROPERTY}[ =;]" "${FILE}" 2>/dev/null) + MATCH_FOUND=$? + + if [ "${ACTION}" = 'get' ]; then + if [ $MATCH_FOUND -ne 0 ]; then + warn "not set" + elif ! echo "${MATCH_LINE}" | grep '=' > /dev/null 2>&1; then + echo "enabled" + else + VALUE=$(echo "${MATCH_LINE}" | sed -E 's/.+= *(.+) *;$/\1/' 2>/dev/null) + if [ $? -ne 0 ]; then + error_notify "Failed to get value." + else + echo "${VALUE}" + fi + fi + else # Setting the value. -- cwells + if [ -n "${VALUE}" ]; then + if echo "${VALUE}" | grep ' ' > /dev/null 2>&1; then # Contains a space, so wrap in quotes. -- cwells + VALUE="'${VALUE}'" + fi + LINE=" ${PROPERTY} = ${VALUE};" + else + LINE=" ${PROPERTY};" + fi + + if [ $MATCH_FOUND -ne 0 ]; then # No match, so insert the property at the end. -- cwells + echo "$(awk -v line="${LINE}" '$0 == "}" { print line; } 1 { print $0; }' "${FILE}")" > "${FILE}" + else # Replace the existing value. -- cwells + sed -i '' -E "s/ *${PROPERTY}[ =;].*/${LINE}/" "${FILE}" + fi + fi +done + +# Only display this message once at the end (not for every jail). -- cwells +if [ "${ACTION}" = 'set' ]; then + info "A restart is required for the changes to be applied. See 'bastille restart ${TARGET}'." +fi + +exit 0 From 351020d1378c57aa3854d4bd48fc4dbda71c2414 Mon Sep 17 00:00:00 2001 From: Chris Wells Date: Sat, 28 Nov 2020 14:03:28 -0500 Subject: [PATCH 06/26] Fix bug preventing commands against stopped jails. --- usr/local/bin/bastille | 2 +- usr/local/share/bastille/cp.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index b984f342..e393c90e 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -154,7 +154,7 @@ clone|cmd|console|convert|cp|edit|export|htop|limits|mount|pkg|rename|service|st fi done else - JAILS=$(jls name | awk "/^${TARGET}$/") + JAILS="${TARGET}" # Ensure the target exists. -- cwells if [ ! -d "${bastille_jailsdir}/${TARGET}" ]; then diff --git a/usr/local/share/bastille/cp.sh b/usr/local/share/bastille/cp.sh index 3e179589..0ed44734 100644 --- a/usr/local/share/bastille/cp.sh +++ b/usr/local/share/bastille/cp.sh @@ -50,8 +50,8 @@ CPSOURCE="${1}" CPDEST="${2}" for _jail in ${JAILS}; do - bastille_jail_path="$(jls -j "${_jail}" path)" info "[${_jail}]:" + bastille_jail_path="${bastille_jailsdir}/${_jail}/root" cp -av "${CPSOURCE}" "${bastille_jail_path}/${CPDEST}" RETURN="$?" if [ "${TARGET}" = "ALL" ]; then From 554f2293c110c204da69e682f1957ad783a6fde7 Mon Sep 17 00:00:00 2001 From: Chris Wells Date: Sat, 28 Nov 2020 17:21:44 -0500 Subject: [PATCH 07/26] Add ability to convert "hook" files to Bastillefile format. --- README.md | 7 ++- usr/local/bin/bastille | 3 ++ usr/local/share/bastille/template.sh | 65 ++++++++++++++++++++++++---- 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0ca7694a..02d83857 100644 --- a/README.md +++ b/README.md @@ -679,7 +679,7 @@ Note: SYSRC requires NO quotes or that quotes (`"`) be escaped. ie; `\"`) Any name provided in the ARG file can be used as a variable in the other hooks. For example, `name=value` in the ARG file will cause instances of `${name}` to be replaced with `value`. The `RENDER` hook can be used to specify existing files or -directories inside the jail whose contents should have the variables replaced. Values can be +directories inside the jail whose contents should have the variables replaced. Values can be specified either through the command line when applying the template or as a default in the ARG file. @@ -748,6 +748,11 @@ CMD hostname > /usr/local/www/nginx-dist/hostname.txt RDR tcp 80 80 ``` +Use the following command to convert a hook-based template into the Bastillefile format: +```shell +bastille template --convert my-template +``` + Applying Templates ------------------ diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index b984f342..ebf3094f 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -153,6 +153,9 @@ clone|cmd|console|convert|cp|edit|export|htop|limits|mount|pkg|rename|service|st JAILS="${JAILS} ${_jail}" fi done + elif [ "${CMD}" = 'template' ] && [ "${TARGET}" = '--convert' ]; then + # This command does not act on a jail, so we are temporarily bypassing the presence/started + # checks. The command will simply convert a template from hooks to a Bastillefile. -- cwells else JAILS=$(jls name | awk "/^${TARGET}$/") diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 2f1e7a7e..9efeea3b 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -32,7 +32,7 @@ . /usr/local/etc/bastille/bastille.conf bastille_usage() { - error_exit "Usage: bastille template TARGET project/template" + error_exit "Usage: bastille template TARGET|--convert project/template" } post_command_hook() { @@ -116,7 +116,61 @@ if [ $# -lt 1 ]; then bastille_usage fi +## global variables TEMPLATE="${1}" +bastille_template=${bastille_templatesdir}/${TEMPLATE} +if [ -z "${HOOKS}" ]; then + HOOKS='LIMITS INCLUDE PRE FSTAB PF PKG OVERLAY CONFIG SYSRC SERVICE CMD RENDER' +fi + +# 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}" + elif [ -d "${bastille_template}" ]; then + cd "${bastille_template}" + else + error_exit "Template not found: ${TEMPLATE}" + fi + + echo "Converting template: ${TEMPLATE}" + + HOOKS="ARG ${HOOKS}" + for _hook in ${HOOKS}; do + if [ -s "${_hook}" ]; then + # Default command is the hook name and default args are the line from the file. -- cwells + _cmd="${_hook}" + _args_template='${_line}' + + # Replace old hook names with Bastille command names. -- cwells + case ${_hook} in + CONFIG|OVERLAY) + _cmd='CP' + _args_template='${_line} /' + ;; + FSTAB) + _cmd='MOUNT' ;; + PF) + _cmd='RDR' ;; + PRE) + _cmd='CMD' ;; + esac + + while read _line; do + if [ -z "${_line}" ]; then + continue + fi + eval "_args=\"${_args_template}\"" + echo "${_cmd} ${_args}" >> Bastillefile + done < "${_hook}" + echo '' >> Bastillefile + rm "${_hook}" + fi + done + + info "Template converted: ${TEMPLATE}" + exit 0 +fi case ${TEMPLATE} in http?://github.com/*/*|http?://gitlab.com/*/*) @@ -128,6 +182,7 @@ case ${TEMPLATE} in fi fi TEMPLATE="${TEMPLATE_DIR}" + bastille_template=${bastille_templatesdir}/${TEMPLATE} ;; */*) if [ ! -d "${bastille_templatesdir}/${TEMPLATE}" ]; then @@ -142,10 +197,6 @@ if [ -z "${JAILS}" ]; then error_exit "Container ${TARGET} is not running." fi -if [ -z "${HOOKS}" ]; then - HOOKS='LIMITS INCLUDE PRE FSTAB PF PKG OVERLAY CONFIG SYSRC SERVICE CMD RENDER' -fi - # Check for an --arg-file parameter. -- cwells for _script_arg in "$@"; do case ${_script_arg} in @@ -166,8 +217,6 @@ if [ -n "${ARG_FILE}" ] && [ ! -f "${ARG_FILE}" ]; then error_exit "File not found: ${ARG_FILE}" fi -## global variables -bastille_template=${bastille_templatesdir}/${TEMPLATE} for _jail in ${JAILS}; do ## jail-specific variables. bastille_jail_path=$(jls -j "${_jail}" path) @@ -322,6 +371,6 @@ for _jail in ${JAILS}; do fi done - info "Template complete." + info "Template applied: ${TEMPLATE}" echo done From 30a8a93fe9ee70e3093e01bc78c15f006a63a067 Mon Sep 17 00:00:00 2001 From: Chris Wells Date: Wed, 25 Nov 2020 20:21:56 -0500 Subject: [PATCH 08/26] Display message about file/directory being rendered. --- usr/local/share/bastille/template.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 8ec25ca8..8df2e738 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -97,8 +97,11 @@ get_arg_value() { render() { _file_path="${1}/${2}" if [ -d "${_file_path}" ]; then # Recursively render every file in this directory. -- cwells + echo "Rendering Directory: ${_file_path}" + find "${_file_path}" \( -type d -name .git -prune \) -o -type f find "${_file_path}" \( -type d -name .git -prune \) -o -type f -print0 | $(eval "xargs -0 sed -i '' ${ARG_REPLACEMENTS}") elif [ -f "${_file_path}" ]; then + echo "Rendering File: ${_file_path}" eval "sed -i '' ${ARG_REPLACEMENTS} '${_file_path}'" else echo -e "${COLOR_YELLOW}Path not found for render: ${2}${COLOR_RESET}" From a47b0a43c9941dad22cc14a4856d8f11a1b108ee Mon Sep 17 00:00:00 2001 From: Chris Wells Date: Sat, 28 Nov 2020 19:03:46 -0500 Subject: [PATCH 09/26] Add missing subcommands (limits/config) to docs. --- docs/chapters/usage.rst | 2 ++ usr/local/bin/bastille | 1 + 2 files changed, 3 insertions(+) diff --git a/docs/chapters/usage.rst b/docs/chapters/usage.rst index b4d9ef48..fb6b9e55 100644 --- a/docs/chapters/usage.rst +++ b/docs/chapters/usage.rst @@ -14,6 +14,7 @@ Usage bootstrap Bootstrap a FreeBSD release for container base. cmd Execute arbitrary command on targeted container(s). clone Clone an existing container. + config Get or set a config value for the targeted container(s). console Console into a running container. convert Convert a Thin container into a Thick container. cp cp(1) files from host to targeted container(s). @@ -24,6 +25,7 @@ Usage help Help about any command. htop Interactive process viewer (requires htop). import Import a specified container. + limits Apply resources limits to targeted container(s). See rctl(8). list List containers (running and stopped). mount Mount a volume inside the targeted container(s). pkg Manipulate binary packages within targeted container(s). See pkg(8). diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index 1aec6845..cca62a60 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -95,6 +95,7 @@ Available Commands: help Help about any command. htop Interactive process viewer (requires htop). import Import a specified container. + limits Apply resources limits to targeted container(s). See rctl(8). list List containers (running and stopped). mount Mount a volume inside the targeted container(s). pkg Manipulate binary packages within targeted container(s). See pkg(8). From 5518273881f7dfe8404b7be0a62d05643c0a5987 Mon Sep 17 00:00:00 2001 From: Chris Wells Date: Sat, 28 Nov 2020 19:49:52 -0500 Subject: [PATCH 10/26] Provide JAIL_NAME and JAIL_IP as default template args. Closes #280. --- README.md | 3 ++- usr/local/share/bastille/template.sh | 16 +++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1f98cdc8..3a28b3e1 100644 --- a/README.md +++ b/README.md @@ -718,7 +718,8 @@ followed by its arguments (omitting the target, which is deduced from the Variables can also be defined using `ARG` with one `name=value` pair per line. Subsequent references to `${name}` would be replaced by `value`. Note that argument values are not available for use until after the point -at which they are defined in the file. +at which they are defined in the file. Both `${JAIL_NAME}` and `${JAIL_IP}` +are made available in templates without having to define them as args. Bastillefile example: diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 2f1e7a7e..d8f2e1f2 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -169,12 +169,17 @@ fi ## global variables bastille_template=${bastille_templatesdir}/${TEMPLATE} for _jail in ${JAILS}; do - ## jail-specific variables. - bastille_jail_path=$(jls -j "${_jail}" path) - info "[${_jail}]:" info "Applying template: ${TEMPLATE}..." + ## jail-specific variables. + bastille_jail_path=$(jls -j "${_jail}" path) + _jail_ip=$(jls -j "${_jail}" ip4.addr 2>/dev/null) + if [ -z "${_jail_ip}" -o "${_jail_ip}" = "-" ]; then + error_notify "Jail IP not found: ${_jail}" + _jail_ip='' # In case it was -. -- cwells + fi + ## TARGET if [ -s "${bastille_template}/TARGET" ]; then if grep -qw "${_jail}" "${bastille_template}/TARGET"; then @@ -189,8 +194,10 @@ for _jail in ${JAILS}; do fi fi + # Build a list of sed commands like this: -e 's/${username}/root/g' -e 's/${domain}/example.com/g' + # Values provided by default (without being defined by the user) are listed here. -- cwells + ARG_REPLACEMENTS="-e 's/\${JAIL_IP}/${_jail_ip}/g' -e 's/\${JAIL_NAME}/${_jail}/g'" # This is parsed outside the HOOKS loop so an ARG file can be used with a Bastillefile. -- cwells - ARG_REPLACEMENTS='' if [ -s "${bastille_template}/ARG" ]; then while read _line; do if [ -z "${_line}" ]; then @@ -201,7 +208,6 @@ for _jail in ${JAILS}; do if [ -z "${_arg_value}" ]; then warn "No value provided for arg: ${_arg_name}" fi - # Build a list of sed commands like this: -e 's/${username}/root/g' -e 's/${domain}/example.com/g' ARG_REPLACEMENTS="${ARG_REPLACEMENTS} -e 's/\${${_arg_name}}/${_arg_value}/g'" done < "${bastille_template}/ARG" fi From b90d8c60f7d07d60a06c6547955bbaa1e6c0beb8 Mon Sep 17 00:00:00 2001 From: Chris Wells Date: Sun, 29 Nov 2020 11:31:14 -0500 Subject: [PATCH 11/26] Update existing limit when a new value is provided. Closes #233. --- usr/local/share/bastille/limits.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/limits.sh b/usr/local/share/bastille/limits.sh index ca48427d..d85687da 100644 --- a/usr/local/share/bastille/limits.sh +++ b/usr/local/share/bastille/limits.sh @@ -63,8 +63,12 @@ for _jail in ${JAILS}; do _rctl_rule="jail:${_jail}:${OPTION}:deny=${VALUE}/jail" - ## if entry doesn't exist, add; else show existing entry - if ! grep -qs "${_rctl_rule}" "${bastille_jailsdir}/${_jail}/rctl.conf"; then + # Check whether the entry already exists and, if so, update it. -- cwells + if grep -qs "jail:${_jail}:${OPTION}:deny" "${bastille_jailsdir}/${_jail}/rctl.conf"; then + _escaped_option=$(echo "${OPTION}" | sed 's/\//\\\//g') + _escaped_rctl_rule=$(echo "${_rctl_rule}" | sed 's/\//\\\//g') + sed -i '' -E "s/jail:${_jail}:${_escaped_option}:deny.+/${_escaped_rctl_rule}/" "${bastille_jailsdir}/${_jail}/rctl.conf" + else # Just append the entry. -- cwells echo "${_rctl_rule}" >> "${bastille_jailsdir}/${_jail}/rctl.conf" fi From c2839f859e6d257e37b98457494e14cc3d4fcbe4 Mon Sep 17 00:00:00 2001 From: Chris Wells Date: Thu, 26 Nov 2020 12:44:40 -0500 Subject: [PATCH 12/26] Use templates for configuring new jails. Allow user to override default templates. Closes #205. --- usr/local/etc/bastille/bastille.conf.sample | 7 + usr/local/share/bastille/bootstrap.sh | 2 + usr/local/share/bastille/create.sh | 128 ++++++++++-------- usr/local/share/bastille/template.sh | 4 +- .../templates/default/base/Bastillefile | 11 ++ .../templates/default/empty/Bastillefile | 0 .../templates/default/thick/Bastillefile | 4 + .../templates/default/thin/Bastillefile | 4 + .../templates/default/vnet/Bastillefile | 13 ++ 9 files changed, 118 insertions(+), 55 deletions(-) create mode 100644 usr/local/share/bastille/templates/default/base/Bastillefile create mode 100644 usr/local/share/bastille/templates/default/empty/Bastillefile create mode 100644 usr/local/share/bastille/templates/default/thick/Bastillefile create mode 100644 usr/local/share/bastille/templates/default/thin/Bastillefile create mode 100644 usr/local/share/bastille/templates/default/vnet/Bastillefile diff --git a/usr/local/etc/bastille/bastille.conf.sample b/usr/local/etc/bastille/bastille.conf.sample index e7bbf5dc..a47da946 100644 --- a/usr/local/etc/bastille/bastille.conf.sample +++ b/usr/local/etc/bastille/bastille.conf.sample @@ -48,3 +48,10 @@ bastille_decompress_xz_options="-c -d -v" ## default bastille_network_loopback="bastille0" ## default: "bastille0" bastille_network_shared="" ## default: "" bastille_network_gateway="" ## default: "" + +## Default Templates +bastille_template_base="default/base" ## default: "default/base" +bastille_template_empty="default/empty" ## default: "default/empty" +bastille_template_thick="default/thick" ## default: "default/thick" +bastille_template_thin="default/thin" ## default: "default/thin" +bastille_template_vnet="default/vnet" ## default: "default/vnet" diff --git a/usr/local/share/bastille/bootstrap.sh b/usr/local/share/bastille/bootstrap.sh index 35ee66f9..9d4380b8 100644 --- a/usr/local/share/bastille/bootstrap.sh +++ b/usr/local/share/bastille/bootstrap.sh @@ -164,6 +164,7 @@ bootstrap_directories() { else mkdir -p "${bastille_templatesdir}" fi + ln -s "${bastille_sharedir}/templates/default" "${bastille_templatesdir}/default" fi ## ${bastille_releasesdir} @@ -304,6 +305,7 @@ bootstrap_template() { else mkdir -p "${bastille_templatesdir}" fi + ln -s "${bastille_sharedir}/templates/default" "${bastille_templatesdir}/default" fi ## define basic variables diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index 141edfba..1be81266 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -326,71 +326,68 @@ create_jail() { ln -s usr/home home fi - ## rc.conf - ## + syslogd_flags="-ss" - ## + sendmail_enable="NO" - ## + sendmail_submit_enable="NO" - ## + sendmail_outbound_enable="NO" - ## + sendmail_msp_queue_enable="NO" - ## + cron_flags="-J 60" ## cedwards 20181118 - if [ ! -f "${bastille_jail_rc_conf}" ]; then - touch "${bastille_jail_rc_conf}" - sysrc -f "${bastille_jail_rc_conf}" syslogd_flags="-ss" - sysrc -f "${bastille_jail_rc_conf}" sendmail_enable="NO" - sysrc -f "${bastille_jail_rc_conf}" sendmail_submit_enable="NO" - sysrc -f "${bastille_jail_rc_conf}" sendmail_outbound_enable="NO" - sysrc -f "${bastille_jail_rc_conf}" sendmail_msp_queue_enable="NO" - sysrc -f "${bastille_jail_rc_conf}" cron_flags="-J 60" + ## TZ: configurable (default: Etc/UTC) + ln -s "/usr/share/zoneinfo/${bastille_tzdata}" etc/localtime - ## VNET specific - if [ -n "${VNET_JAIL}" ]; then - ## rename interface to generic vnet0 - uniq_epair=$(grep vnet.interface "${bastille_jailsdir}/${NAME}/jail.conf" | awk '{print $3}' | sed 's/;//') - /usr/sbin/sysrc -f "${bastille_jail_rc_conf}" "ifconfig_${uniq_epair}_name"=vnet0 + # Post-creation jail misc configuration + # Create a dummy fstab file + touch "etc/fstab" + # Disables adjkerntz, avoids spurious error messages + sed -i '' 's|[0-9],[0-9]\{2\}.*[0-9]-[0-9].*root.*kerntz -a|#& # Disabled by bastille|' "etc/crontab" - ## if 0.0.0.0 set DHCP - ## else set static address - if [ "${IP}" == "0.0.0.0" ]; then - /usr/sbin/sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="SYNCDHCP" - else - /usr/sbin/sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="inet ${IP}" - if [ -n "${bastille_network_gateway}" ]; then - /usr/sbin/sysrc -f "${bastille_jail_rc_conf}" defaultrouter="${bastille_network_gateway}" - else - /usr/sbin/sysrc -f "${bastille_jail_rc_conf}" defaultrouter="$(netstat -rn | awk '/default/ {print $2}')" - fi - fi - - ## VNET requires jib script - if [ ! "$(command -v jib)" ]; then - 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 - fi + ## VNET specific + if [ -n "${VNET_JAIL}" ]; then + ## VNET requires jib script + if [ ! "$(command -v jib)" ]; then + 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 fi fi fi - - ## resolv.conf (default: copy from host) - if [ ! -f "${bastille_jail_resolv_conf}" ]; then - cp -L "${bastille_resolv_conf}" "${bastille_jail_resolv_conf}" - fi - - ## TZ: configurable (default: Etc/UTC) - ln -s "/usr/share/zoneinfo/${bastille_tzdata}" etc/localtime else ## Generate minimal configuration for empty jail generate_minimal_conf fi - # Post-creation jail misc configuration - # Creates a dummy fstab file - # Disables adjkerntz, avoids spurious error messages # Set strict permissions on the jail by default - if [ -z "${EMPTY_JAIL}" ]; then - touch "etc/fstab" - sed -i '' 's|[0-9],[0-9]\{2\}.*[0-9]-[0-9].*root.*kerntz -a|#& # Disabled by bastille|' "etc/crontab" - fi chmod 0700 "${bastille_jailsdir}/${NAME}" + + # Jail must be started before applying the default template. -- cwells + bastille start "${NAME}" + + if [ -n "${VNET_JAIL}" ]; then + if [ -n ${bastille_template_vnet} ]; then + ## rename interface to generic vnet0 + uniq_epair=$(grep vnet.interface "${bastille_jailsdir}/${NAME}/jail.conf" | awk '{print $3}' | sed 's/;//') + + _gateway='' + _ifconfig=SYNCDHCP + if [ "${IP}" != "0.0.0.0" ]; then # not using DHCP, so set static address. + _ifconfig="inet ${IP}" + if [ -n "${bastille_network_gateway}" ]; then + _gateway="${bastille_network_gateway}" + else + _gateway="$(netstat -rn | awk '/default/ {print $2}')" + fi + fi + bastille template "${NAME}" ${bastille_template_vnet} --arg BASE_TEMPLATE="${bastille_template_base}" --arg HOST_RESOLV_CONF="${bastille_resolv_conf}" --arg EPAIR="${uniq_epair}" --arg GATEWAY="${_gateway}" --arg IFCONFIG="${_ifconfig}" + fi + elif [ -n "${THICK_JAIL}" ]; then + if [ -n ${bastille_template_thick} ]; then + bastille template "${NAME}" ${bastille_template_thick} --arg BASE_TEMPLATE="${bastille_template_base}" --arg HOST_RESOLV_CONF="${bastille_resolv_conf}" + fi + elif [ -n "${EMPTY_JAIL}" ]; then + if [ -n ${bastille_template_empty} ]; then + bastille template "${NAME}" ${bastille_template_empty} --arg BASE_TEMPLATE="${bastille_template_base}" --arg HOST_RESOLV_CONF="${bastille_resolv_conf}" + fi + else # Thin jail. + if [ -n ${bastille_template_thin} ]; then + bastille template "${NAME}" ${bastille_template_thin} --arg BASE_TEMPLATE="${bastille_template_base}" --arg HOST_RESOLV_CONF="${bastille_resolv_conf}" + fi + fi + + # Apply values changed by the template. -- cwells + bastille restart "${NAME}" } # Handle special-case commands first. @@ -520,7 +517,7 @@ if [ -z "${EMPTY_JAIL}" ]; then fi ## check if interface is valid - if [ -n "${INTERFACE}" ]; then + if [ -n "${INTERFACE}" ]; then validate_netif validate_netconf else @@ -535,4 +532,27 @@ if [ -n "${NAME}" ]; then running_jail fi +# May not exist on deployments created before Bastille 0.7.20200714, so creating it. -- cwells +if [ ! -e "${bastille_templatesdir}/default" ]; then + ln -s "${bastille_sharedir}/templates/default" "${bastille_templatesdir}/default" +fi + +# These variables were added after Bastille 0.7.20200714, so they may not exist in the user's config. +# We're checking for existence of the variables rather than empty since empty is a valid value. -- cwells +if [ -z ${bastille_template_base+x} ]; then + bastille_template_base='default/base' +fi +if [ -z ${bastille_template_empty+x} ]; then + bastille_template_empty='default/empty' +fi +if [ -z ${bastille_template_thick+x} ]; then + bastille_template_thick='default/thick' +fi +if [ -z ${bastille_template_thin+x} ]; then + bastille_template_thin='default/thin' +fi +if [ -z ${bastille_template_vnet+x} ]; then + bastille_template_vnet='default/vnet' +fi + create_jail "${NAME}" "${RELEASE}" "${IP}" "${INTERFACE}" diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 2f1e7a7e..80d7b9d9 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -232,13 +232,15 @@ for _jail in ${JAILS}; do continue ;; cmd) + # Escape single-quotes in the command being executed. -- cwells + _args=$(echo "${_args}" | sed "s/'/'\\\\''/g") # Allow redirection within the jail. -- cwells _args="sh -c '${_args}'" ;; cp|copy) _cmd='cp' # Convert relative "from" path into absolute path inside the template directory. -- cwells - if [ "${_args%${_args#?}}" != '/' ]; then + if [ "${_args%${_args#?}}" != '/' ] && [ "${_args%${_args#??}}" != '"/' ]; then _args="${bastille_template}/${_args}" fi ;; diff --git a/usr/local/share/bastille/templates/default/base/Bastillefile b/usr/local/share/bastille/templates/default/base/Bastillefile new file mode 100644 index 00000000..7418fba6 --- /dev/null +++ b/usr/local/share/bastille/templates/default/base/Bastillefile @@ -0,0 +1,11 @@ +ARG HOST_RESOLV_CONF=/etc/resolv.conf + +CMD touch /etc/rc.conf +SYSRC syslogd_flags="-ss" +SYSRC sendmail_enable="NO" +SYSRC sendmail_submit_enable="NO" +SYSRC sendmail_outbound_enable="NO" +SYSRC sendmail_msp_queue_enable="NO" +SYSRC cron_flags="-J 60" + +CP "${HOST_RESOLV_CONF}" etc/resolv.conf diff --git a/usr/local/share/bastille/templates/default/empty/Bastillefile b/usr/local/share/bastille/templates/default/empty/Bastillefile new file mode 100644 index 00000000..e69de29b diff --git a/usr/local/share/bastille/templates/default/thick/Bastillefile b/usr/local/share/bastille/templates/default/thick/Bastillefile new file mode 100644 index 00000000..37e450e6 --- /dev/null +++ b/usr/local/share/bastille/templates/default/thick/Bastillefile @@ -0,0 +1,4 @@ +ARG BASE_TEMPLATE=default/base +ARG HOST_RESOLV_CONF=/etc/resolv.conf + +INCLUDE ${BASE_TEMPLATE} --arg HOST_RESOLV_CONF="${HOST_RESOLV_CONF}" diff --git a/usr/local/share/bastille/templates/default/thin/Bastillefile b/usr/local/share/bastille/templates/default/thin/Bastillefile new file mode 100644 index 00000000..37e450e6 --- /dev/null +++ b/usr/local/share/bastille/templates/default/thin/Bastillefile @@ -0,0 +1,4 @@ +ARG BASE_TEMPLATE=default/base +ARG HOST_RESOLV_CONF=/etc/resolv.conf + +INCLUDE ${BASE_TEMPLATE} --arg HOST_RESOLV_CONF="${HOST_RESOLV_CONF}" diff --git a/usr/local/share/bastille/templates/default/vnet/Bastillefile b/usr/local/share/bastille/templates/default/vnet/Bastillefile new file mode 100644 index 00000000..92b76fc6 --- /dev/null +++ b/usr/local/share/bastille/templates/default/vnet/Bastillefile @@ -0,0 +1,13 @@ +ARG BASE_TEMPLATE=default/base +ARG HOST_RESOLV_CONF=/etc/resolv.conf + +INCLUDE ${BASE_TEMPLATE} --arg HOST_RESOLV_CONF="${HOST_RESOLV_CONF}" + +ARG EPAIR +ARG GATEWAY +ARG IFCONFIG="SYNCDHCP" + +SYSRC ifconfig_${EPAIR}_name=vnet0 +SYSRC ifconfig_vnet0="${IFCONFIG}" +# GATEWAY will be empty for a DHCP config. -- cwells +CMD if [ -n "${GATEWAY}" ]; then /usr/sbin/sysrc defaultrouter="${GATEWAY}"; fi From 7d44a39a011a5c84edc18048570bce09e7bb9fef Mon Sep 17 00:00:00 2001 From: Andrew Date: Tue, 1 Dec 2020 13:03:15 +0100 Subject: [PATCH 13/26] Respect jexec.fib parameter in console command If parameter "exec.fib" exists in jail.conf, use it when jexec'ing into the jail. --- usr/local/share/bastille/console.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/console.sh b/usr/local/share/bastille/console.sh index 30066ade..baec8da6 100644 --- a/usr/local/share/bastille/console.sh +++ b/usr/local/share/bastille/console.sh @@ -29,6 +29,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. . /usr/local/share/bastille/common.sh +. /usr/local/etc/bastille/bastille.conf usage() { error_exit "Usage: bastille console TARGET [user]'" @@ -64,12 +65,22 @@ validate_user() { fi } +check_fib() { + 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 +} + for _jail in ${JAILS}; do info "[${_jail}]:" if [ -n "${USER}" ]; then validate_user else - jexec -l "${_jail}" /usr/bin/login -f root + check_fib + ${_setfib} jexec -l "${_jail}" /usr/bin/login -f root fi echo done From c6ad100d8a253da0ffe338aba0de56816a5211b4 Mon Sep 17 00:00:00 2001 From: Jose Date: Wed, 2 Dec 2020 06:41:45 -0400 Subject: [PATCH 14/26] Update help usage on update command --- usr/local/share/bastille/update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/local/share/bastille/update.sh b/usr/local/share/bastille/update.sh index d6a00ac3..acb958b2 100644 --- a/usr/local/share/bastille/update.sh +++ b/usr/local/share/bastille/update.sh @@ -32,7 +32,7 @@ . /usr/local/etc/bastille/bastille.conf usage() { - error_exit "Usage: bastille update [release|container]" + error_exit "Usage: bastille update [release|container] | [option]" } # Handle special-case commands first. From 02f9df6cc01925f3ab6b7f5d24721393ea9ec1e0 Mon Sep 17 00:00:00 2001 From: Petru Garstea Date: Fri, 11 Dec 2020 15:47:48 -0500 Subject: [PATCH 15/26] log rctl events to /var/log/messages --- usr/local/share/bastille/limits.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/limits.sh b/usr/local/share/bastille/limits.sh index ca48427d..33a2bf88 100644 --- a/usr/local/share/bastille/limits.sh +++ b/usr/local/share/bastille/limits.sh @@ -62,13 +62,15 @@ for _jail in ${JAILS}; do info "[${_jail}]:" _rctl_rule="jail:${_jail}:${OPTION}:deny=${VALUE}/jail" + _rctl_rule_log="jail:${_jail}:${OPTION}:log=${VALUE}/jail" ## if entry doesn't exist, add; else show existing entry if ! grep -qs "${_rctl_rule}" "${bastille_jailsdir}/${_jail}/rctl.conf"; then echo "${_rctl_rule}" >> "${bastille_jailsdir}/${_jail}/rctl.conf" + echo "${_rctl_rule_log}" >> "${bastille_jailsdir}/${_jail}/rctl.conf" fi echo -e "${OPTION} ${VALUE}" - rctl -a "${_rctl_rule}" + rctl -a "${_rctl_rule}" "${_rctl_rule_log}" echo -e "${COLOR_RESET}" done From 54f6ef62cdc15de2fa8b9cb7e7c31aeff38fa2aa Mon Sep 17 00:00:00 2001 From: Chris Wells Date: Sat, 28 Nov 2020 23:22:17 -0500 Subject: [PATCH 16/26] Properly escape config property and value. --- usr/local/share/bastille/config.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/config.sh b/usr/local/share/bastille/config.sh index b40835b5..0203c6b6 100644 --- a/usr/local/share/bastille/config.sh +++ b/usr/local/share/bastille/config.sh @@ -71,7 +71,8 @@ for _jail in ${JAILS}; do continue fi - MATCH_LINE=$(grep "^\s*${PROPERTY}[ =;]" "${FILE}" 2>/dev/null) + ESCAPED_PROPERTY=$(echo "${PROPERTY}" | sed 's/\./\\\./g') + MATCH_LINE=$(grep "^ *${ESCAPED_PROPERTY}[ =;]" "${FILE}" 2>/dev/null) MATCH_FOUND=$? if [ "${ACTION}" = 'get' ]; then @@ -89,6 +90,7 @@ for _jail in ${JAILS}; do fi else # Setting the value. -- cwells if [ -n "${VALUE}" ]; then + VALUE=$(echo "${VALUE}" | sed 's/\//\\\//g') if echo "${VALUE}" | grep ' ' > /dev/null 2>&1; then # Contains a space, so wrap in quotes. -- cwells VALUE="'${VALUE}'" fi @@ -100,7 +102,7 @@ for _jail in ${JAILS}; do if [ $MATCH_FOUND -ne 0 ]; then # No match, so insert the property at the end. -- cwells echo "$(awk -v line="${LINE}" '$0 == "}" { print line; } 1 { print $0; }' "${FILE}")" > "${FILE}" else # Replace the existing value. -- cwells - sed -i '' -E "s/ *${PROPERTY}[ =;].*/${LINE}/" "${FILE}" + sed -i '' -E "s/ *${ESCAPED_PROPERTY}[ =;].*/${LINE}/" "${FILE}" fi fi done From 7675286cd30c251e492d73160455913d8b5a8326 Mon Sep 17 00:00:00 2001 From: Chris Wells Date: Sat, 12 Dec 2020 19:17:20 -0500 Subject: [PATCH 17/26] Fix grep when UTF-8 is not used. Support tabs and spaces in templates/config. --- usr/local/share/bastille/config.sh | 2 +- usr/local/share/bastille/template.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/usr/local/share/bastille/config.sh b/usr/local/share/bastille/config.sh index 0203c6b6..42f0160c 100644 --- a/usr/local/share/bastille/config.sh +++ b/usr/local/share/bastille/config.sh @@ -72,7 +72,7 @@ for _jail in ${JAILS}; do fi ESCAPED_PROPERTY=$(echo "${PROPERTY}" | sed 's/\./\\\./g') - MATCH_LINE=$(grep "^ *${ESCAPED_PROPERTY}[ =;]" "${FILE}" 2>/dev/null) + MATCH_LINE=$(grep "^[[:blank:]]*${ESCAPED_PROPERTY}[[:blank:]=;]" "${FILE}" 2>/dev/null) MATCH_FOUND=$? if [ "${ACTION}" = 'get' ]; then diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 7e052fbc..8ce21b75 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -266,7 +266,7 @@ for _jail in ${JAILS}; do if [ -s "${bastille_template}/Bastillefile" ]; then # Ignore blank lines and comments. -- cwells - SCRIPT=$(grep -v '^\s*$' "${bastille_template}/Bastillefile" | grep -v '^\s*#') + SCRIPT=$(grep -v '^[[:blank:]]*$' "${bastille_template}/Bastillefile" | grep -v '^[[:blank:]]*#') # Use a newline as the separator. -- cwells IFS=' ' From 7150b633919fb4d1f1218187bd00c79a8d7998c9 Mon Sep 17 00:00:00 2001 From: Christer Edwards Date: Sun, 13 Dec 2020 11:05:25 -0700 Subject: [PATCH 18/26] update VNET devfs documentation --- README.md | 14 +++++++++----- docs/chapters/networking.rst | 4 ---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 82474a94..e57334b5 100644 --- a/README.md +++ b/README.md @@ -368,10 +368,6 @@ VNET also requires a custom `devfs` ruleset. Create the file as needed on the ho **/etc/devfs.rules** ``` [bastille_vnet=13] -add include $devfsrules_hide_all -add include $devfsrules_unhide_basic -add include $devfsrules_unhide_login -add include $devfsrules_jail add path 'bpf*' unhide ``` @@ -621,9 +617,17 @@ ishmael ~ # bastille destroy folsom Deleting Container: folsom. Note: container console logs not destroyed. /usr/local/bastille/logs/folsom_console.log - ``` +This command can also be used to destroy old releases that are no longer +needed. + +```shell +ishmael ~ # bastille destroy 11.1-RELEASE +Deleting base: 11.1-RELEASE +``` + + bastille template ----------------- Looking for ready made CI/CD validated [Bastille diff --git a/docs/chapters/networking.rst b/docs/chapters/networking.rst index 6a4cc3e9..c476b3da 100644 --- a/docs/chapters/networking.rst +++ b/docs/chapters/networking.rst @@ -76,10 +76,6 @@ host system: ## /etc/devfs.rules (NOT .conf) [bastille_vnet=13] - add include $devfsrules_hide_all - add include $devfsrules_unhide_basic - add include $devfsrules_unhide_login - add include $devfsrules_jail add path 'bpf*' unhide Lastly, you may want to consider these three `sysctl` values: From a3d2f69b711fac9b687e2e828a57a79b735c80a2 Mon Sep 17 00:00:00 2001 From: Christer Edwards Date: Sun, 13 Dec 2020 11:10:29 -0700 Subject: [PATCH 19/26] cleanup patch; vnet specific --- README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/README.md b/README.md index e57334b5..e56a51a0 100644 --- a/README.md +++ b/README.md @@ -619,14 +619,6 @@ Note: container console logs not destroyed. /usr/local/bastille/logs/folsom_console.log ``` -This command can also be used to destroy old releases that are no longer -needed. - -```shell -ishmael ~ # bastille destroy 11.1-RELEASE -Deleting base: 11.1-RELEASE -``` - bastille template ----------------- From 857b5d430bb3987b9b178b4cc01d305ff80157da Mon Sep 17 00:00:00 2001 From: Christer Edwards Date: Sun, 13 Dec 2020 11:11:15 -0700 Subject: [PATCH 20/26] cleanup patch; vnet specific --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e56a51a0..42cd325f 100644 --- a/README.md +++ b/README.md @@ -617,8 +617,8 @@ ishmael ~ # bastille destroy folsom Deleting Container: folsom. Note: container console logs not destroyed. /usr/local/bastille/logs/folsom_console.log -``` +``` bastille template ----------------- From a56c37983cd698e0d22f909621006207d0738390 Mon Sep 17 00:00:00 2001 From: Chris Wells Date: Sun, 13 Dec 2020 20:22:59 -0500 Subject: [PATCH 21/26] Verify interface exists when starting non-vnet jail. Closes #128. --- usr/local/share/bastille/start.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/start.sh b/usr/local/share/bastille/start.sh index 145c7be5..66c1fe83 100644 --- a/usr/local/share/bastille/start.sh +++ b/usr/local/share/bastille/start.sh @@ -67,11 +67,21 @@ for _jail in ${JAILS}; do ## test if not running elif [ ! "$(jls name | awk "/^${_jail}$/")" ]; then + # Verify that the configured interface exists. -- cwells + if [ "$(bastille config $_jail get vnet)" != 'enabled' ]; then + _interface=$(bastille config $_jail get interface) + if ! ifconfig | grep "^${_interface}:" >/dev/null; then + error_notify "Error: ${_interface} interface does not exist." + continue + fi + fi + ## warn if matching configured (but not online) ip4.addr, ignore if there's no ip4.addr entry ip=$(grep 'ip4.addr' "${bastille_jailsdir}/${_jail}/jail.conf" | awk '{print $3}' | sed 's/\;//g') if [ -n "${ip}" ]; then if ifconfig | grep -w "${ip}" >/dev/null; then - error_exit "Error: IP address (${ip}) already in use." + error_notify "Error: IP address (${ip}) already in use." + continue fi fi From cbd60032fcbae10c3ec5671f5bb3b47e37ec01a8 Mon Sep 17 00:00:00 2001 From: Bike Dude Date: Tue, 15 Dec 2020 09:12:02 +0100 Subject: [PATCH 22/26] add ZFS check on bootstrap --- usr/local/share/bastille/bootstrap.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/usr/local/share/bastille/bootstrap.sh b/usr/local/share/bastille/bootstrap.sh index 35ee66f9..bd5c177a 100644 --- a/usr/local/share/bastille/bootstrap.sh +++ b/usr/local/share/bastille/bootstrap.sh @@ -61,6 +61,19 @@ if [ "${bastille_zfs_enable}" = "YES" ]; then fi fi +if [ "$(sysrc -n zfs_enable)" = "YES" ] && [ ! "${bastille_zfs_enable}" = "YES" ]; then + warn "ZFS is enabled in rc.conf but not bastille.conf. Do you want to continue? (N|y)" + read answer + case $answer in + no|No|n|N|"") + error_exit "ERROR: Bootstrap interrupted" + ;; + yes|Yes|y|Y) + continue + ;; + esac +fi + validate_release_url() { ## check upstream url, else warn user if [ -n "${NAME_VERIFY}" ]; then From 32a12783268b7d0b49ccf918716aa4ac95f7226c Mon Sep 17 00:00:00 2001 From: Bike Dude Date: Tue, 15 Dec 2020 09:21:26 +0100 Subject: [PATCH 23/26] add ZFS check on bootstrap --- usr/local/share/bastille/bootstrap.sh | 29 ++++++++++++++------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/usr/local/share/bastille/bootstrap.sh b/usr/local/share/bastille/bootstrap.sh index bd5c177a..f0c24681 100644 --- a/usr/local/share/bastille/bootstrap.sh +++ b/usr/local/share/bastille/bootstrap.sh @@ -42,7 +42,21 @@ help|-h|--help) ;; esac -# Validate ZFS parameters first. +#Validate if ZFS is enabled in rc.conf and bastille.conf. +if [ "$(sysrc -n zfs_enable)" = "YES" ] && [ ! "${bastille_zfs_enable}" = "YES" ]; then + warn "ZFS is enabled in rc.conf but not bastille.conf. Do you want to continue? (N|y)" + read answer + case $answer in + no|No|n|N|"") + error_exit "ERROR: Missing ZFS parameters. See bastille_zfs_enable." + ;; + yes|Yes|y|Y) + continue + ;; + esac +fi + +# Validate ZFS parameters. if [ "${bastille_zfs_enable}" = "YES" ]; then ## check for the ZFS pool and bastille prefix if [ -z "${bastille_zfs_zpool}" ]; then @@ -61,19 +75,6 @@ if [ "${bastille_zfs_enable}" = "YES" ]; then fi fi -if [ "$(sysrc -n zfs_enable)" = "YES" ] && [ ! "${bastille_zfs_enable}" = "YES" ]; then - warn "ZFS is enabled in rc.conf but not bastille.conf. Do you want to continue? (N|y)" - read answer - case $answer in - no|No|n|N|"") - error_exit "ERROR: Bootstrap interrupted" - ;; - yes|Yes|y|Y) - continue - ;; - esac -fi - validate_release_url() { ## check upstream url, else warn user if [ -n "${NAME_VERIFY}" ]; then From ca8819d7b6fa7e88baa7f01dca8d3c40754de627 Mon Sep 17 00:00:00 2001 From: Bike Dude Date: Tue, 15 Dec 2020 10:21:11 +0100 Subject: [PATCH 24/26] stop.sh: clear rdr --- usr/local/share/bastille/stop.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/usr/local/share/bastille/stop.sh b/usr/local/share/bastille/stop.sh index 1aac57e2..bfe67932 100644 --- a/usr/local/share/bastille/stop.sh +++ b/usr/local/share/bastille/stop.sh @@ -55,6 +55,10 @@ for _jail in ${JAILS}; do pfctl -q -t jails -T delete "$(jls -j ${_jail} ip4.addr)" fi fi + + if [ "$(bastille rdr ${_jail} list)" ]; then + bastille rdr ${_jail} clear + fi ## remove rctl limits if [ -s "${bastille_jailsdir}/${_jail}/rctl.conf" ]; then From a0feac3f669a6228087ef2a61351248799443d6d Mon Sep 17 00:00:00 2001 From: Christer Edwards Date: Fri, 1 Jan 2021 09:13:44 -0700 Subject: [PATCH 25/26] version bumps for release preparation --- README.md | 2 +- docs/chapters/installation.rst | 2 +- docs/chapters/networking.rst | 23 +++++++++++++++++++++++ docs/conf.py | 4 ++-- usr/local/bin/bastille | 2 +- 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 42cd325f..629c7695 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ Use "bastille command -h|--help" for more information about a command. ``` -## 0.7-beta +## 0.8-beta This document outlines the basic usage of the Bastille container management framework. This release is still considered beta. diff --git a/docs/chapters/installation.rst b/docs/chapters/installation.rst index 19b89c85..25c1c852 100644 --- a/docs/chapters/installation.rst +++ b/docs/chapters/installation.rst @@ -4,7 +4,7 @@ Bastille is available in the official FreeBSD ports tree at `sysutils/bastille`. Binary packages available in `quarterly` and `latest` repositories. -Current version is `0.7.20200714`. +Current version is `0.8.20210101`. To install from the FreeBSD package repository: diff --git a/docs/chapters/networking.rst b/docs/chapters/networking.rst index c476b3da..fb52e8a8 100644 --- a/docs/chapters/networking.rst +++ b/docs/chapters/networking.rst @@ -86,6 +86,29 @@ Lastly, you may want to consider these three `sysctl` values: net.link.bridge.pfil_onlyip=0 net.link.bridge.pfil_member=0 +**Regarding Routes** + +Bastille will attempt to auto-detect the default route from the host system and +assign it to the VNET container. This auto-detection may not always be accurate +for your needs for the particular container. In this case you'll need to add +a default route manually or define the preferred default route in the +`bastille.conf`. + +.. code-block:: shell + + bastille sysrc TARGET defaultrouter=aa.bb.cc.dd + bastille service TARGET routing restart + +To define a default route / gateway for all VNET containers define the value in +`bastille.conf`: + +.. code-block:: shell + + bastille_network_gateway=aa.bb.cc.dd + +This config change will apply the defined gateway to any new containers. +Existing containers will need to be manually updated. + Public Network ============== diff --git a/docs/conf.py b/docs/conf.py index e8d83fbe..ca3c958e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,9 +12,9 @@ copyright = '2018-2020, Christer Edwards' author = 'Christer Edwards' # The short X.Y version -version = '0.7.20200714' +version = '0.8.20210101' # The full version, including alpha/beta/rc tags -release = '0.7.20200714-beta' +release = '0.8.20210101-beta' # -- General configuration --------------------------------------------------- diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index 7f22b06b..46ec8f2d 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -70,7 +70,7 @@ bastille_perms_check() { bastille_perms_check ## version -BASTILLE_VERSION="0.7.20200714" +BASTILLE_VERSION="0.8.20210101" usage() { cat << EOF From 83a83e087e9a1ea23b23529c8f9331fb3b0e07aa Mon Sep 17 00:00:00 2001 From: Christer Edwards Date: Fri, 1 Jan 2021 09:23:26 -0700 Subject: [PATCH 26/26] adding a couple vnet exceptions for ip4.addr checks --- usr/local/share/bastille/rdr.sh | 8 +++++--- usr/local/share/bastille/template.sh | 10 ++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index 1fe1c63e..be8c62e2 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -58,9 +58,11 @@ if [ -z "${JAIL_NAME}" ]; then fi # Check jail ip4 address valid -JAIL_IP=$(jls -j "${TARGET}" ip4.addr 2>/dev/null) -if [ -z "${JAIL_IP}" -o "${JAIL_IP}" = "-" ]; then - error_exit "Jail IP not found: ${TARGET}" +if [ "$(bastille config $TARGET get vnet)" != 'enabled' ]; then + JAIL_IP=$(jls -j "${TARGET}" ip4.addr 2>/dev/null) + if [ -z "${JAIL_IP}" -o "${JAIL_IP}" = "-" ]; then + error_exit "Jail IP not found: ${TARGET}" + fi fi # Check rdr-anchor is setup in pf.conf diff --git a/usr/local/share/bastille/template.sh b/usr/local/share/bastille/template.sh index 418f01c5..d43ba95c 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -226,10 +226,12 @@ for _jail in ${JAILS}; do ## jail-specific variables. bastille_jail_path=$(jls -j "${_jail}" path) - _jail_ip=$(jls -j "${_jail}" ip4.addr 2>/dev/null) - if [ -z "${_jail_ip}" -o "${_jail_ip}" = "-" ]; then - error_notify "Jail IP not found: ${_jail}" - _jail_ip='' # In case it was -. -- cwells + if [ "$(bastille config $TARGET get vnet)" != 'enabled' ]; then + _jail_ip=$(jls -j "${_jail}" ip4.addr 2>/dev/null) + if [ -z "${_jail_ip}" -o "${_jail_ip}" = "-" ]; then + error_notify "Jail IP not found: ${_jail}" + _jail_ip='' # In case it was -. -- cwells + fi fi ## TARGET