From ae2b0ea0cb6a9d8c2e9a893182c55d5b3885e7fb Mon Sep 17 00:00:00 2001 From: Jose Date: Sat, 2 Nov 2019 16:05:49 -0400 Subject: [PATCH 1/4] Added bootstrap checksum validation and minor fixes --- usr/local/share/bastille/bootstrap.sh | 18 +++++++++++++++-- usr/local/share/bastille/destroy.sh | 5 +++++ usr/local/share/bastille/list.sh | 29 ++++++++++++++++----------- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/usr/local/share/bastille/bootstrap.sh b/usr/local/share/bastille/bootstrap.sh index d2e64fec..a8219f65 100644 --- a/usr/local/share/bastille/bootstrap.sh +++ b/usr/local/share/bastille/bootstrap.sh @@ -262,18 +262,32 @@ bootstrap_release() { echo -e "${COLOR_GREEN}Extracting FreeBSD ${RELEASE} ${_archive}.txz.${COLOR_RESET}" /usr/bin/tar -C "${bastille_releasesdir}/${RELEASE}" -xf "${bastille_cachedir}/${RELEASE}/${_archive}.txz" else - for _archive in ${bastille_bootstrap_archives}; do + ## get the manifest for dist files checksum validation + if [ ! -f "${bastille_cachedir}/${RELEASE}/MANIFEST" ]; then + fetch ${UPSTREAM_URL}/MANIFEST -o ${bastille_cachedir}/${RELEASE}/MANIFEST + fi + ## 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 + ## compare checksums on the fetched dist files + if [ -f "${bastille_cachedir}/${RELEASE}/${_archive}.txz" ]; then + SHA256_DIST=$(grep -w "${_archive}.txz" ${bastille_cachedir}/${RELEASE}/MANIFEST | awk '{print $2}') + SHA256_FILE=$(sha256 -q ${bastille_cachedir}/${RELEASE}/${_archive}.txz) + if [ "${SHA256_FILE}" != "${SHA256_DIST}" ]; then + echo -e "${COLOR_RED}Failed validation for ${_archive}.txz, please retry bootstrap!${COLOR_RESET}" + rm ${bastille_cachedir}/${RELEASE}/${_archive}.txz + exit 1 + fi + fi + ## 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 diff --git a/usr/local/share/bastille/destroy.sh b/usr/local/share/bastille/destroy.sh index 5542f481..9f2887c0 100644 --- a/usr/local/share/bastille/destroy.sh +++ b/usr/local/share/bastille/destroy.sh @@ -79,6 +79,11 @@ destroy_jail() { destroy_rel() { bastille_rel_base="${bastille_releasesdir}/${NAME}" ## dir + ## check if this release have containers child + if grep -qwo "${NAME}" ${bastille_jailsdir}/*/fstab 2>/dev/null; then + echo -e "${COLOR_RED} ${NAME} base appears to have containers child.${COLOR_RESET}" + exit 1 + fi if [ ! -d "${bastille_rel_base}" ]; then echo -e "${COLOR_RED}Release base not found.${COLOR_RESET}" diff --git a/usr/local/share/bastille/list.sh b/usr/local/share/bastille/list.sh index ea55ae4e..ab373491 100644 --- a/usr/local/share/bastille/list.sh +++ b/usr/local/share/bastille/list.sh @@ -47,23 +47,28 @@ if [ $# -gt 0 ]; then usage ;; release|releases) - REL_LIST=$(ls "${bastille_releasesdir}" | sed "s/\n//g") - for _REL in ${REL_LIST}; do - if [ -f "${bastille_releasesdir}/${_REL}/root/.profile" ]; then - echo "${bastille_releasesdir}/${_REL}" - fi - done + if [ -d "${bastille_releasesdir}" ]; then + REL_LIST=$(ls "${bastille_releasesdir}" | sed "s/\n//g") + for _REL in ${REL_LIST}; do + if [ -f "${bastille_releasesdir}/${_REL}/root/.profile" ]; then + #echo "${bastille_releasesdir}/${_REL}" + echo "${_REL}" + fi + done + fi ;; template|templates) find "${bastille_templatesdir}" -type d -maxdepth 2 ;; jail|jails) - JAIL_LIST=$(ls "${bastille_jailsdir}" | sed "s/\n//g") - for _JAIL in ${JAIL_LIST}; do - if [ -f "${bastille_jailsdir}/${_JAIL}/jail.conf" ]; then - echo "${_JAIL}" - fi - done + if [ -d "${bastille_jailsdir}" ]; then + JAIL_LIST=$(ls "${bastille_jailsdir}" | sed "s/\n//g") + for _JAIL in ${JAIL_LIST}; do + if [ -f "${bastille_jailsdir}/${_JAIL}/jail.conf" ]; then + echo "${_JAIL}" + fi + done + fi ;; log|logs) find "${bastille_logsdir}" -type f -maxdepth 1 From 3c5d9619257eafef1e0f44043dcf7299cb5c45de Mon Sep 17 00:00:00 2001 From: Jose Date: Sun, 3 Nov 2019 00:15:02 -0400 Subject: [PATCH 2/4] Scan only related jails before base release deletion --- usr/local/share/bastille/destroy.sh | 43 +++++++++++++++++------------ 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/usr/local/share/bastille/destroy.sh b/usr/local/share/bastille/destroy.sh index 9f2887c0..6d452a6a 100644 --- a/usr/local/share/bastille/destroy.sh +++ b/usr/local/share/bastille/destroy.sh @@ -79,33 +79,42 @@ destroy_jail() { destroy_rel() { bastille_rel_base="${bastille_releasesdir}/${NAME}" ## dir + ## check if this release have containers child - if grep -qwo "${NAME}" ${bastille_jailsdir}/*/fstab 2>/dev/null; then - echo -e "${COLOR_RED} ${NAME} base appears to have containers child.${COLOR_RESET}" - exit 1 + BASE_HASCHILD="0" + if [ -d "${bastille_jailsdir}" ]; then + JAIL_LIST=$(ls "${bastille_jailsdir}" | sed "s/\n//g") + for _jail in ${JAIL_LIST}; do + if grep -qwo "${NAME}" ${bastille_jailsdir}/${_jail}/fstab 2>/dev/null; then + echo -e "${COLOR_RED}Notice: (${_jail}) depends on ${NAME} base.${COLOR_RESET}" + BASE_HASCHILD="1" + fi + done fi 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} + else + if [ "${BASE_HASCHILD}" -eq "0" ]; 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 - fi - if [ -d "${bastille_rel_base}" ]; then - ## removing all flags - chflags -R noschg ${bastille_rel_base} + if [ -d "${bastille_rel_base}" ]; then + ## removing all flags + chflags -R noschg ${bastille_rel_base} - ## remove jail base - rm -rf ${bastille_rel_base} + ## remove jail base + rm -rf ${bastille_rel_base} + fi + echo + else + echo -e "${COLOR_RED}Cannot destroy base with containers child.${COLOR_RESET}" fi - echo fi } From 4f675151575e4dd56013cd7d560e64d6ffab0855 Mon Sep 17 00:00:00 2001 From: Jose Date: Sun, 3 Nov 2019 01:58:29 -0400 Subject: [PATCH 3/4] Create required jail/root dataset on ZFS setups --- usr/local/share/bastille/create.sh | 4 +++- usr/local/share/bastille/destroy.sh | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index 5f39a838..033082f8 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -83,7 +83,9 @@ create_jail() { if [ ! -d "${bastille_jailsdir}/${NAME}" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then if [ ! -z "${bastille_zfs_zpool}" ]; then - zfs create ${bastille_zfs_options} -o mountpoint=${bastille_jailsdir}/${NAME} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME} + ## create required zfs datasets + zfs create ${bastille_zfs_options} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME} + zfs create ${bastille_zfs_options} -o mountpoint=${bastille_jailsdir}/${NAME}/root ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root fi else mkdir -p "${bastille_jailsdir}/${NAME}" diff --git a/usr/local/share/bastille/destroy.sh b/usr/local/share/bastille/destroy.sh index 6d452a6a..023eb16f 100644 --- a/usr/local/share/bastille/destroy.sh +++ b/usr/local/share/bastille/destroy.sh @@ -55,6 +55,8 @@ destroy_jail() { echo -e "${COLOR_GREEN}Deleting Jail: ${NAME}.${COLOR_RESET}" if [ "${bastille_zfs_enable}" = "YES" ]; then if [ ! -z "${bastille_zfs_zpool}" ]; then + ## remove zfs datasets individually + zfs destroy ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root zfs destroy ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME} fi fi From 9bc8837f77a689a3cde26188637c187f766c14e0 Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 8 Nov 2019 02:37:45 -0400 Subject: [PATCH 4/4] Simplify release name handling, code improvements and fixes --- usr/local/share/bastille/bootstrap.sh | 104 +++++++++++++++----------- usr/local/share/bastille/create.sh | 29 +++---- usr/local/share/bastille/destroy.sh | 25 ++++++- 3 files changed, 99 insertions(+), 59 deletions(-) diff --git a/usr/local/share/bastille/bootstrap.sh b/usr/local/share/bastille/bootstrap.sh index a8219f65..0a349944 100644 --- a/usr/local/share/bastille/bootstrap.sh +++ b/usr/local/share/bastille/bootstrap.sh @@ -258,18 +258,53 @@ bootstrap_release() { for _archive in ${bastille_bootstrap_archives}; do ## 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 FreeBSD ${RELEASE} ${_archive}.txz.${COLOR_RESET}" /usr/bin/tar -C "${bastille_releasesdir}/${RELEASE}" -xf "${bastille_cachedir}/${RELEASE}/${_archive}.txz" + if [ $? -ne 0 ]; then + echo -e "${COLOR_RED}Failed to extract ${_archive}.txz.${COLOR_RESET}" + exit 1 + fi else ## get the manifest for dist files checksum validation if [ ! -f "${bastille_cachedir}/${RELEASE}/MANIFEST" ]; then - fetch ${UPSTREAM_URL}/MANIFEST -o ${bastille_cachedir}/${RELEASE}/MANIFEST + fetch ${UPSTREAM_URL}/MANIFEST -o ${bastille_cachedir}/${RELEASE}/MANIFEST || FETCH_VALIDATION="1" fi + if [ "${FETCH_VALIDATION}" -ne "0" ]; then + ## perform cleanup only for stale/empty directories on failure + if [ "${bastille_zfs_enable}" = "YES" ]; then + if [ ! -z "${bastille_zfs_zpool}" ]; then + if [ ! "$(ls -A ${bastille_cachedir}/${RELEASE})" ]; then + zfs destroy ${bastille_zfs_zpool}/${bastille_zfs_prefix}/cache/${RELEASE} + fi + if [ ! "$(ls -A ${bastille_releasesdir}/${RELEASE})" ]; then + zfs destroy ${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE} + fi + fi + fi + if [ -d "${bastille_cachedir}/${RELEASE}" ]; then + if [ ! "$(ls -A ${bastille_cachedir}/${RELEASE})" ]; then + rm -rf ${bastille_cachedir}/${RELEASE} + fi + fi + if [ -d "${bastille_releasesdir}/${RELEASE}" ]; then + if [ ! "$(ls -A ${bastille_releasesdir}/${RELEASE})" ]; then + rm -rf ${bastille_releasesdir}/${RELEASE} + fi + fi + echo -e "${COLOR_RED}Bootstrap failed.${COLOR_RESET}" + exit 1 + fi + ## fetch for missing dist files if [ ! -f "${bastille_cachedir}/${RELEASE}/${_archive}.txz" ]; then fetch ${UPSTREAM_URL}/${_archive}.txz -o ${bastille_cachedir}/${RELEASE}/${_archive}.txz + if [ $? -ne 0 ]; then + ## alert only if unable to fetch additional dist files + echo -e "${COLOR_RED}Failed to fetch ${_archive}.txz.${COLOR_RESET}" + fi fi ## compare checksums on the fetched dist files @@ -287,6 +322,10 @@ bootstrap_release() { 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" + if [ $? -ne 0 ]; then + echo -e "${COLOR_RED}Failed to extract ${_archive}.txz.${COLOR_RESET}" + exit 1 + fi fi fi done @@ -373,56 +412,33 @@ bootstrap_template() { HW_MACHINE=$(sysctl hw.machine | awk '{ print $2 }') HW_MACHINE_ARCH=$(sysctl hw.machine_arch | awk '{ print $2 }') +RELEASE="${1}" -# Filter sane release names +## Filter sane release names case "${1}" in -11.2-RELEASE) - RELEASE="${1}" - UPSTREAM_URL="http://ftp.freebsd.org/pub/FreeBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/11.2-RELEASE" +*-RELEASE|*-release|*-RC1|*-rc1|*-RC2|*-rc2) +## check for FreeBSD releases name +NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '^([1-9]{2,2})\.[0-9](-RELEASE|-RC[1-2])$' | tr '[:lower:]' '[:upper:]') +if [ -n "${NAME_VERIFY}" ]; then + RELEASE="${NAME_VERIFY}" + UPSTREAM_URL="http://ftp.freebsd.org/pub/FreeBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/${RELEASE}" bootstrap_directories bootstrap_release +else + usage +fi ;; -11.3-RELEASE) - RELEASE="${1}" - UPSTREAM_URL="http://ftp.freebsd.org/pub/FreeBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/11.3-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" - bootstrap_directories - bootstrap_release - ;; -12.1-RC1) - RELEASE="${1}" - UPSTREAM_URL="http://ftp.freebsd.org/pub/FreeBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/12.1-RC1" - bootstrap_directories - bootstrap_release - ;; -12.1-RC2) - RELEASE="${1}" - UPSTREAM_URL="http://ftp.freebsd.org/pub/FreeBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/12.1-RC2" - bootstrap_directories - bootstrap_release - ;; -12.1-RELEASE) - RELEASE="${1}" - UPSTREAM_URL="http://ftp.freebsd.org/pub/FreeBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/12.1-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" - 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" +*-stable-LAST|*-STABLE-last|*-stable-last|*-STABLE-LAST) +## check for HardenedBSD releases name +NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '^([1-9]{2,2})(-stable-LAST|-STABLE-last|-stable-last|-STABLE-LAST)$' | sed 's/STABLE/stable/g' | sed 's/last/LAST/g') +if [ -n "${NAME_VERIFY}" ]; then + RELEASE="${NAME_VERIFY}" + UPSTREAM_URL="https://installer.hardenedbsd.org/pub/HardenedBSD/releases/${HW_MACHINE}/${HW_MACHINE_ARCH}/hardenedbsd-${RELEASE}" bootstrap_directories bootstrap_release +else + usage +fi ;; http?://github.com/*/*|http?://gitlab.com/*/*) BASTILLE_TEMPLATE_URL=${1} diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index 033082f8..3c31175c 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -204,20 +204,23 @@ INTERFACE="$4" ## verify release case "${RELEASE}" in -11.3-RELEASE|11.3-release) - RELEASE="11.3-RELEASE" +*-RELEASE|*-release|*-RC1|*-rc1|*-RC2|*-rc2) +## check for FreeBSD releases name +NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '^([1-9]{2,2})\.[0-9](-RELEASE|-RC[1-2])$' | tr '[:lower:]' '[:upper:]') +if [ -n "${NAME_VERIFY}" ]; then + RELEASE="${NAME_VERIFY}" +else + usage +fi ;; -11.2-RELEASE|11.2-release) - RELEASE="11.2-RELEASE" - ;; -12.0-RELEASE|12.0-release) - RELEASE="12.0-RELEASE" - ;; -11-stable-LAST|11-STABLE-last|11-stable-last|11-STABLE-LAST) - RELEASE="11-stable-LAST" - ;; -12-stable-LAST|12-STABLE-last|12-stable-last|12-STABLE-LAST) - RELEASE="12-stable-LAST" +*-stable-LAST|*-STABLE-last|*-stable-last|*-STABLE-LAST) +## check for HardenedBSD releases name +NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '^([1-9]{2,2})(-stable-LAST|-STABLE-last|-stable-last|-STABLE-LAST)$' | sed 's/STABLE/stable/g' | sed 's/last/LAST/g') +if [ -n "${NAME_VERIFY}" ]; then + RELEASE="${NAME_VERIFY}" +else + usage +fi ;; *) echo -e "${COLOR_RED}Unknown Release.${COLOR_RESET}" diff --git a/usr/local/share/bastille/destroy.sh b/usr/local/share/bastille/destroy.sh index 023eb16f..174ca361 100644 --- a/usr/local/share/bastille/destroy.sh +++ b/usr/local/share/bastille/destroy.sh @@ -134,8 +134,29 @@ fi NAME="$1" ## check what should we clean -if echo "${NAME}" | grep -qwE '^([0-9]{1,2})\.[0-9]-RELEASE$'; then +case "${NAME}" in +*-RELEASE|*-release|*-RC1|*-rc1|*-RC2|*-rc2) +## check for FreeBSD releases name +NAME_VERIFY=$(echo "${NAME}" | grep -iwE '^([1-9]{2,2})\.[0-9](-RELEASE|-RC[1-2])$' | tr '[:lower:]' '[:upper:]') +if [ -n "${NAME_VERIFY}" ]; then + NAME="${NAME_VERIFY}" destroy_rel else - destroy_jail + usage fi + ;; +*-stable-LAST|*-STABLE-last|*-stable-last|*-STABLE-LAST) +## check for HardenedBSD releases name +NAME_VERIFY=$(echo "${NAME}" | grep -iwE '^([1-9]{2,2})(-stable-LAST|-STABLE-last|-stable-last|-STABLE-LAST)$' | sed 's/STABLE/stable/g' | sed 's/last/LAST/g') +if [ -n "${NAME_VERIFY}" ]; then + NAME="${NAME_VERIFY}" + destroy_rel +else + usage +fi + ;; +*) + ## just destroy a jail + destroy_jail + ;; +esac