From cbe04f2f6835babb8fe7a56db4544613ecfda967 Mon Sep 17 00:00:00 2001 From: Jose Date: Thu, 24 Oct 2019 17:02:50 -0400 Subject: [PATCH] Bastille improvements and fixes --- usr/local/bin/bastille | 2 +- usr/local/share/bastille/bootstrap.sh | 76 +++++++++++++++++++++------ usr/local/share/bastille/create.sh | 37 ++++++++++--- usr/local/share/bastille/destroy.sh | 44 ++++++++++++++-- 4 files changed, 131 insertions(+), 28 deletions(-) diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index 251fddcb..d3d2d47e 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -85,7 +85,7 @@ Available Commands: console Console into a running container. cp cp(1) files from host to targeted container(s). create Create a new container. - destroy Destroy a stopped container. + destroy Destroy a stopped container or a FreeBSD release. help Help about any command htop Interactive process viewer (requires htop). list List containers (running and stopped). diff --git a/usr/local/share/bastille/bootstrap.sh b/usr/local/share/bastille/bootstrap.sh index fddfaacd..45a75bd3 100644 --- a/usr/local/share/bastille/bootstrap.sh +++ b/usr/local/share/bastille/bootstrap.sh @@ -43,6 +43,29 @@ help|-h|--help) ;; esac +# Validate ZFS parameters first. +if [ "${bastille_zfs_enable}" = "YES" ]; then + ## check for the ZFS pool and bastille prefix + if [ -z "${bastille_zfs_zpool}" ]; then + echo -e "${COLOR_RED}ERROR: Missing ZFS parameters, see bastille_zfs_zpool.${COLOR_RESET}" + exit 1 + elif [ -z "${bastille_zfs_prefix}" ]; then + echo -e "${COLOR_RED}ERROR: Missing ZFS parameters, see bastille_zfs_prefix.${COLOR_RESET}" + exit 1 + elif ! zfs list "${bastille_zfs_zpool}" > /dev/null 2>&1; then + echo -e "${COLOR_RED}ERROR: ${bastille_zfs_zpool} is not a ZFS pool.${COLOR_RESET}" + exit 1 + fi + + ## check for the ZFS dataset prefix if already exist + if [ -d "/${bastille_zfs_zpool}/${bastille_zfs_prefix}" ]; then + if ! zfs list "${bastille_zfs_zpool}/${bastille_zfs_prefix}" > /dev/null 2>&1; then + echo -e "${COLOR_RED}ERROR: ${bastille_zfs_zpool}/${bastille_zfs_prefix} is not a ZFS dataset.${COLOR_RESET}" + exit 1 + fi + fi +fi + bootstrap_network_interfaces() { ## test for both options empty @@ -160,6 +183,15 @@ bootstrap_directories() { else mkdir -p "${bastille_cachedir}/${RELEASE}" fi + ## create subsequent cache/XX.X-RELEASE datasets + elif [ ! -d "${bastille_cachedir}/${RELEASE}" ]; then + if [ "${bastille_zfs_enable}" = "YES" ]; then + if [ ! -z "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint=${bastille_cachedir}/${RELEASE} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/cache/${RELEASE} + fi + else + mkdir -p "${bastille_cachedir}/${RELEASE}" + fi fi ## ${bastille_jailsdir} @@ -201,10 +233,19 @@ bootstrap_directories() { if [ ! -z "${bastille_zfs_zpool}" ]; then zfs create ${bastille_zfs_options} -o mountpoint=${bastille_releasesdir} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases zfs create ${bastille_zfs_options} -o mountpoint=${bastille_releasesdir}/${RELEASE} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE} - fi + fi else mkdir -p "${bastille_releasesdir}/${RELEASE}" fi + ## create subsequent releases/XX.X-RELEASE datasets + elif [ ! -d "${bastille_releasesdir}/${RELEASE}" ]; then + if [ "${bastille_zfs_enable}" = "YES" ]; then + if [ ! -z "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint=${bastille_releasesdir}/${RELEASE} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE} + fi + else + mkdir -p "${bastille_releasesdir}/${RELEASE}" + fi fi } @@ -216,20 +257,23 @@ bootstrap_release() { fi for _archive in ${bastille_bootstrap_archives}; do + ## check if the dist files already exists then extract if [ -f "${bastille_cachedir}/${RELEASE}/${_archive}.txz" ]; then echo -e "${COLOR_GREEN}Extracting FreeBSD ${RELEASE} ${_archive}.txz.${COLOR_RESET}" /usr/bin/tar -C "${bastille_releasesdir}/${RELEASE}" -xf "${bastille_cachedir}/${RELEASE}/${_archive}.txz" - fi - done + else + for _archive in ${bastille_bootstrap_archives}; do + ## fetch for missing dist files + if [ ! -f "${bastille_cachedir}/${RELEASE}/${_archive}.txz" ]; then + fetch ${UPSTREAM_URL}/${_archive}.txz -o ${bastille_cachedir}/${RELEASE}/${_archive}.txz + fi - for _archive in ${bastille_bootstrap_archives}; do - if [ ! -f "${bastille_cachedir}/${RELEASE}/${_archive}.txz" ]; then - fetch ${UPSTREAM_URL}/${_archive}.txz -o ${bastille_cachedir}/${RELEASE}/${_archive}.txz - fi - - if [ -f "${bastille_cachedir}/${RELEASE}/${_archive}.txz" ]; then - echo -e "${COLOR_GREEN}Extracting FreeBSD ${RELEASE} ${_archive}.txz.${COLOR_RESET}" - /usr/bin/tar -C "${bastille_releasesdir}/${RELEASE}" -xf "${bastille_cachedir}/${RELEASE}/${_archive}.txz" + ## extract the fetched dist files + if [ -f "${bastille_cachedir}/${RELEASE}/${_archive}.txz" ]; then + echo -e "${COLOR_GREEN}Extracting FreeBSD ${RELEASE} ${_archive}.txz.${COLOR_RESET}" + /usr/bin/tar -C "${bastille_releasesdir}/${RELEASE}" -xf "${bastille_cachedir}/${RELEASE}/${_archive}.txz" + fi + done fi done echo @@ -320,31 +364,31 @@ HW_MACHINE_ARCH=$(sysctl hw.machine_arch | awk '{ print $2 }') case "${1}" in 11.3-RELEASE) RELEASE="${1}" - UPSTREAM_URL="http://ftp.freebsd.org/pub/FreeBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/11.3-RELEASE/" + UPSTREAM_URL="http://ftp.freebsd.org/pub/FreeBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/11.3-RELEASE" bootstrap_directories bootstrap_release ;; 11.2-RELEASE) RELEASE="${1}" - UPSTREAM_URL="http://ftp.freebsd.org/pub/FreeBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/11.2-RELEASE/" + UPSTREAM_URL="http://ftp.freebsd.org/pub/FreeBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/11.2-RELEASE" bootstrap_directories bootstrap_release ;; 12.0-RELEASE) RELEASE="${1}" - UPSTREAM_URL="http://ftp.freebsd.org/pub/FreeBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/12.0-RELEASE/" + UPSTREAM_URL="http://ftp.freebsd.org/pub/FreeBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/12.0-RELEASE" bootstrap_directories bootstrap_release ;; 11-stable-LAST) RELEASE="${1}" - UPSTREAM_URL="https://installer.hardenedbsd.org/pub/HardenedBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/hardenedbsd-11-stable-LAST/" + UPSTREAM_URL="https://installer.hardenedbsd.org/pub/HardenedBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/hardenedbsd-11-stable-LAST" bootstrap_directories bootstrap_release ;; 12-stable-LAST) RELEASE="${1}" - UPSTREAM_URL="https://installer.hardenedbsd.org/pub/HardenedBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/hardenedbsd-12-stable-LAST/" + UPSTREAM_URL="https://installer.hardenedbsd.org/pub/HardenedBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/hardenedbsd-12-stable-LAST" bootstrap_directories bootstrap_release ;; diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index 59bdcbab..5f39a838 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -32,7 +32,7 @@ . /usr/local/etc/bastille/bastille.conf usage() { - echo -e "${COLOR_RED}Usage: bastille create name release ip.${COLOR_RESET}" + echo -e "${COLOR_RED}Usage: bastille create name release ip | interface.${COLOR_RESET}" exit 1 } @@ -43,7 +43,6 @@ running_jail() { validate_ip() { local IFS ip=${IP} - if expr "$ip" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; then IFS=. set $ip @@ -55,10 +54,22 @@ validate_ip() { done echo -e "${COLOR_GREEN}Valid: ($ip).${COLOR_RESET}" else + echo -e "${COLOR_RED}Invalid: ($ip).${COLOR_RESET}" exit 1 fi } +validate_netif() { + local LIST_INTERFACES=$(ifconfig -l) + interface=${INTERFACE} + if echo "${LIST_INTERFACES}" | grep -qwo "${INTERFACE}"; then + echo -e "${COLOR_GREEN}Valid: ($interface).${COLOR_RESET}" + else + echo -e "${COLOR_RED}Invalid: ($interface).${COLOR_RESET}" + exit 1 + fi +} + create_jail() { bastille_jail_base="${bastille_jailsdir}/${NAME}/root/.bastille" ## dir bastille_jail_template="${bastille_jailsdir}/${NAME}/root/.template" ## dir @@ -100,6 +111,9 @@ create_jail() { if [ ! -z ${bastille_jail_loopback} ] && [ -z ${bastille_jail_external} ]; then local bastille_jail_conf_interface=${bastille_jail_interface} fi + if [ ! -z ${INTERFACE} ]; then + local bastille_jail_conf_interface=${INTERFACE} + fi echo -e "interface = ${bastille_jail_conf_interface};\nhost.hostname = ${NAME};\nexec.consolelog = \ ${bastille_jail_log};\npath = ${bastille_jail_path};\nip6 = \ disable;\nsecurelevel = 2;\ndevfs_ruleset = 4;\nenforce_statfs = \ @@ -115,6 +129,9 @@ fi echo echo -e "${COLOR_GREEN}NAME: ${NAME}.${COLOR_RESET}" echo -e "${COLOR_GREEN}IP: ${IP}.${COLOR_RESET}" + if [ ! -z ${INTERFACE} ]; then + echo -e "${COLOR_GREEN}INTERFACE: ${INTERFACE}.${COLOR_RESET}" + fi echo -e "${COLOR_GREEN}RELEASE: ${RELEASE}.${COLOR_RESET}" echo @@ -169,7 +186,7 @@ help|-h|--help) ;; esac -if [ $# -gt 3 ] || [ $# -lt 3 ]; then +if [ $# -gt 4 ] || [ $# -lt 3 ]; then usage fi @@ -181,6 +198,7 @@ fi NAME="$1" RELEASE="$2" IP="$3" +INTERFACE="$4" ## verify release case "${RELEASE}" in @@ -225,8 +243,15 @@ if running_jail ${NAME}; then fi ## check if ip address is valid -if ! validate_ip ${IP}; then - echo -e "${COLOR_RED}Invalid: ($ip).${COLOR_RESET}" +if [ ! -z ${IP} ]; then + validate_ip +else + usage fi -create_jail ${NAME} ${RELEASE} ${IP} +## check if interface is valid +if [ ! -z ${INTERFACE} ]; then + validate_netif +fi + +create_jail ${NAME} ${RELEASE} ${IP} ${INTERFACE} diff --git a/usr/local/share/bastille/destroy.sh b/usr/local/share/bastille/destroy.sh index 7fa129a7..5542f481 100644 --- a/usr/local/share/bastille/destroy.sh +++ b/usr/local/share/bastille/destroy.sh @@ -59,11 +59,13 @@ destroy_jail() { fi fi - ## removing all flags - chflags -R noschg ${bastille_jail_base} + if [ -d "${bastille_jail_base}" ]; then + ## removing all flags + chflags -R noschg ${bastille_jail_base} - ## remove jail base - rm -rf ${bastille_jail_base} + ## remove jail base + rm -rf ${bastille_jail_base} + fi ## archive jail log if [ -f "${bastille_jail_log}" ]; then @@ -75,6 +77,33 @@ destroy_jail() { fi } +destroy_rel() { + bastille_rel_base="${bastille_releasesdir}/${NAME}" ## dir + + if [ ! -d "${bastille_rel_base}" ]; then + echo -e "${COLOR_RED}Release base not found.${COLOR_RESET}" + exit 1 + fi + + if [ -d "${bastille_rel_base}" ]; then + echo -e "${COLOR_GREEN}Deleting base: ${NAME}.${COLOR_RESET}" + if [ "${bastille_zfs_enable}" = "YES" ]; then + if [ ! -z "${bastille_zfs_zpool}" ]; then + zfs destroy ${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${NAME} + fi + fi + + if [ -d "${bastille_rel_base}" ]; then + ## removing all flags + chflags -R noschg ${bastille_rel_base} + + ## remove jail base + rm -rf ${bastille_rel_base} + fi + echo + fi +} + # Handle special-case commands first. case "$1" in help|-h|--help) @@ -88,4 +117,9 @@ fi NAME="$1" -destroy_jail +## check what should we clean +if echo "${NAME}" | grep -qwE '^([0-9]{1,2})\.[0-9]-RELEASE$'; then + destroy_rel +else + destroy_jail +fi