Merge pull request #207 from JRGTH/master

Feature add, create empty jail and minor maintenance
This commit is contained in:
Christer Edwards
2020-05-20 09:51:16 -06:00
committed by GitHub
4 changed files with 333 additions and 264 deletions

View File

@@ -3,16 +3,16 @@
##################### #####################
## default paths ## default paths
bastille_prefix=/usr/local/bastille ## default: "/usr/local/bastille" bastille_prefix="/usr/local/bastille" ## default: "/usr/local/bastille"
bastille_backupsdir=${bastille_prefix}/backups ## default: ${bastille_prefix}/backups bastille_backupsdir="${bastille_prefix}/backups" ## default: "${bastille_prefix}/backups"
bastille_cachedir=${bastille_prefix}/cache ## default: ${bastille_prefix}/cache bastille_cachedir="${bastille_prefix}/cache" ## default: "${bastille_prefix}/cache"
bastille_jailsdir=${bastille_prefix}/jails ## default: ${bastille_prefix}/jails bastille_jailsdir="${bastille_prefix}/jails" ## default: "${bastille_prefix}/jails"
bastille_logsdir=${bastille_prefix}/logs ## default: ${bastille_prefix}/logs bastille_logsdir="${bastille_prefix}/logs" ## default: "${bastille_prefix}/logs"
bastille_releasesdir=${bastille_prefix}/releases ## default: ${bastille_prefix}/releases bastille_releasesdir="${bastille_prefix}/releases" ## default: "${bastille_prefix}/releases"
bastille_templatesdir=${bastille_prefix}/templates ## default: ${bastille_prefix}/templates bastille_templatesdir="${bastille_prefix}/templates" ## default: "${bastille_prefix}/templates"
## bastille scripts directory (assumed by bastille pkg) ## bastille scripts directory (assumed by bastille pkg)
bastille_sharedir=/usr/local/share/bastille ## default: "/usr/local/share/bastille" bastille_sharedir="/usr/local/share/bastille" ## default: "/usr/local/share/bastille"
## bootstrap archives (base, lib32, ports, src, test) ## bootstrap archives (base, lib32, ports, src, test)
bastille_bootstrap_archives="base" ## default: "base" bastille_bootstrap_archives="base" ## default: "base"

View File

@@ -36,13 +36,25 @@ usage() {
exit 1 exit 1
} }
error_notify() {
# Notify message on error and exit
echo -e "$*" >&2
exit 1
}
running_jail() { running_jail() {
if [ -n "$(jls name | awk "/^${NAME}$/")" ]; then if [ -n "$(jls name | awk "/^${NAME}$/")" ]; then
echo -e "${COLOR_RED}A running jail matches name.${COLOR_RESET}" error_notify "${COLOR_RED}A running jail matches name.${COLOR_RESET}"
exit 1
elif [ -d "${bastille_jailsdir}/${NAME}" ]; then elif [ -d "${bastille_jailsdir}/${NAME}" ]; then
echo -e "${COLOR_RED}Jail: ${NAME} already created.${COLOR_RESET}" error_notify "${COLOR_RED}Jail: ${NAME} already created.${COLOR_RESET}"
exit 1 fi
}
validate_name() {
local NAME_VERIFY=${NAME}
local NAME_SANITY=$(echo "${NAME_VERIFY}" | tr -c -d 'a-zA-Z0-9-_')
if [ "${NAME_VERIFY}" != "${NAME_SANITY}" ]; then
error_notify "${COLOR_RED}Container names may not contain special characters!${COLOR_RESET}"
fi fi
} }
@@ -72,8 +84,7 @@ validate_ip() {
echo -e "${COLOR_GREEN}Valid: (${IP}).${COLOR_RESET}" echo -e "${COLOR_GREEN}Valid: (${IP}).${COLOR_RESET}"
fi fi
else else
echo -e "${COLOR_RED}Invalid: (${IP}).${COLOR_RESET}" error_notify "${COLOR_RED}Invalid: (${IP}).${COLOR_RESET}"
exit 1
fi fi
fi fi
} }
@@ -83,15 +94,13 @@ validate_netif() {
if echo "${LIST_INTERFACES} VNET" | grep -qwo "${INTERFACE}"; then if echo "${LIST_INTERFACES} VNET" | grep -qwo "${INTERFACE}"; then
echo -e "${COLOR_GREEN}Valid: (${INTERFACE}).${COLOR_RESET}" echo -e "${COLOR_GREEN}Valid: (${INTERFACE}).${COLOR_RESET}"
else else
echo -e "${COLOR_RED}Invalid: (${INTERFACE}).${COLOR_RESET}" error_notify "${COLOR_RED}Invalid: (${INTERFACE}).${COLOR_RESET}"
exit 1
fi fi
} }
validate_netconf() { validate_netconf() {
if [ -n "${bastille_network_loopback}" ] && [ -n "${bastille_network_shared}" ]; then if [ -n "${bastille_network_loopback}" ] && [ -n "${bastille_network_shared}" ]; then
echo -e "${COLOR_RED}Invalid network configuration.${COLOR_RESET}" error_notify "${COLOR_RED}Invalid network configuration.${COLOR_RESET}"
exit 1
fi fi
} }
@@ -104,6 +113,17 @@ validate_release() {
fi fi
} }
generate_minimal_conf() {
cat << EOF > "${bastille_jail_conf}"
${NAME} {
host.hostname = ${NAME};
mount.fstab = ${bastille_jail_fstab};
path = ${bastille_jail_path};
}
EOF
touch "${bastille_jail_fstab}"
}
generate_jail_conf() { generate_jail_conf() {
cat << EOF > "${bastille_jail_conf}" cat << EOF > "${bastille_jail_conf}"
${NAME} { ${NAME} {
@@ -187,176 +207,187 @@ create_jail() {
fi fi
fi fi
else else
mkdir -p "${bastille_jailsdir}/${NAME}" mkdir -p "${bastille_jailsdir}/${NAME}/root"
fi fi
fi fi
if [ ! -d "${bastille_jail_base}" ]; then if [ -z "${EMPTY_JAIL}" ]; then
mkdir -p "${bastille_jail_base}" if [ ! -d "${bastille_jail_base}" ]; then
fi mkdir -p "${bastille_jail_base}"
if [ ! -d "${bastille_jail_path}/usr/home" ]; then
mkdir -p "${bastille_jail_path}/usr/home"
fi
if [ ! -d "${bastille_jail_path}/usr/local" ]; then
mkdir -p "${bastille_jail_path}/usr/local"
fi
if [ ! -d "${bastille_jail_template}" ]; then
mkdir -p "${bastille_jail_template}"
fi
if [ ! -f "${bastille_jail_fstab}" ]; then
if [ -z "${THICK_JAIL}" ]; then
echo -e "${bastille_releasesdir}/${RELEASE} ${bastille_jail_base} nullfs ro 0 0" > "${bastille_jail_fstab}"
else
touch "${bastille_jail_fstab}"
fi
fi
if [ ! -f "${bastille_jail_conf}" ]; then
if [ -z "${bastille_network_loopback}" ] && [ -n "${bastille_network_shared}" ]; then
local bastille_jail_conf_interface=${bastille_network_shared}
fi
if [ -n "${bastille_network_loopback}" ] && [ -z "${bastille_network_shared}" ]; then
local bastille_jail_conf_interface=${bastille_network_loopback}
fi
if [ -n "${INTERFACE}" ]; then
local bastille_jail_conf_interface=${INTERFACE}
fi fi
## generate the jail configuration file if [ ! -d "${bastille_jail_path}/usr/local" ]; then
if [ -n "${VNET_JAIL}" ]; then mkdir -p "${bastille_jail_path}/usr/local"
generate_vnet_jail_conf
else
generate_jail_conf
fi fi
fi
## using relative paths here if [ ! -d "${bastille_jail_template}" ]; then
## MAKE SURE WE'RE IN THE RIGHT PLACE mkdir -p "${bastille_jail_template}"
cd "${bastille_jail_path}"
echo
echo -e "${COLOR_GREEN}NAME: ${NAME}.${COLOR_RESET}"
echo -e "${COLOR_GREEN}IP: ${IP}.${COLOR_RESET}"
if [ -n "${INTERFACE}" ]; then
echo -e "${COLOR_GREEN}INTERFACE: ${INTERFACE}.${COLOR_RESET}"
fi
echo -e "${COLOR_GREEN}RELEASE: ${RELEASE}.${COLOR_RESET}"
echo
if [ -z "${THICK_JAIL}" ]; then
for _link in bin boot lib libexec rescue sbin usr/bin usr/include usr/lib usr/lib32 usr/libdata usr/libexec usr/sbin usr/share usr/src; do
ln -sf /.bastille/${_link} ${_link}
done
fi
## link home properly
ln -s usr/home home
if [ -z "${THICK_JAIL}" ]; then
## rw
## copy only required files for thin jails
FILE_LIST=".cshrc .profile COPYRIGHT dev etc media mnt net proc root tmp var usr/obj usr/tests"
for files in ${FILE_LIST}; do
if [ -f "${bastille_releasesdir}/${RELEASE}/${files}" ] || [ -d "${bastille_releasesdir}/${RELEASE}/${files}" ]; then
cp -a "${bastille_releasesdir}/${RELEASE}/${files}" "${bastille_jail_path}/${files}"
if [ "$?" -ne 0 ]; then
## notify and clean stale files/directories
echo -e "${COLOR_RED}Failed to copy release files, please retry create!${COLOR_RESET}"
bastille destroy "${NAME}"
exit 1
fi
fi
done
else
echo -e "${COLOR_GREEN}Creating a thickjail, this may take a while...${COLOR_RESET}"
if [ "${bastille_zfs_enable}" = "YES" ]; then
if [ -n "${bastille_zfs_zpool}" ]; then
## perform release base replication
## sane bastille zfs options
ZFS_OPTIONS=$(echo ${bastille_zfs_options} | sed 's/-o//g')
## take a temp snapshot of the base release
SNAP_NAME="bastille-$(date +%Y-%m-%d-%H%M%S)"
zfs snapshot "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}"@"${SNAP_NAME}"
## replicate the release base to the new thickjail and set the default mountpoint
zfs send -R "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}"@"${SNAP_NAME}" | \
zfs receive "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root"
zfs set ${ZFS_OPTIONS} mountpoint=none "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root"
zfs inherit mountpoint "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root"
## cleanup temp snapshots initially
zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}"@"${SNAP_NAME}"
zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root"@"${SNAP_NAME}"
if [ "$?" -ne 0 ]; then
## notify and clean stale files/directories
echo -e "${COLOR_RED}Failed release base replication, please retry create!${COLOR_RESET}"
bastille destroy "${NAME}"
exit 1
fi
fi
else
## copy all files for thick jails
cp -a "${bastille_releasesdir}/${RELEASE}/" "${bastille_jail_path}"
if [ "$?" -ne 0 ]; then
## notify and clean stale files/directories
echo -e "${COLOR_RED}Failed to copy release files, please retry create!${COLOR_RESET}"
bastille destroy "${NAME}"
exit 1
fi
fi fi
fi
## rc.conf if [ ! -f "${bastille_jail_fstab}" ]; then
## + syslogd_flags="-ss" if [ -z "${THICK_JAIL}" ]; then
## + sendmail_none="NONE" echo -e "${bastille_releasesdir}/${RELEASE} ${bastille_jail_base} nullfs ro 0 0" > "${bastille_jail_fstab}"
## + 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=NONE
sysrc -f "${bastille_jail_rc_conf}" cron_flags='-J 60'
## 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
## 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 else
/usr/sbin/sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="inet ${IP}" touch "${bastille_jail_fstab}"
if [ -n "${bastille_network_gateway}" ]; then fi
/usr/sbin/sysrc -f "${bastille_jail_rc_conf}" defaultrouter="${bastille_network_gateway}" fi
else
/usr/sbin/sysrc -f "${bastille_jail_rc_conf}" defaultrouter="$(netstat -rn | awk '/default/ {print $2}')" if [ ! -f "${bastille_jail_conf}" ]; then
fi if [ -z "${bastille_network_loopback}" ] && [ -n "${bastille_network_shared}" ]; then
local bastille_jail_conf_interface=${bastille_network_shared}
fi
if [ -n "${bastille_network_loopback}" ] && [ -z "${bastille_network_shared}" ]; then
local bastille_jail_conf_interface=${bastille_network_loopback}
fi
if [ -n "${INTERFACE}" ]; then
local bastille_jail_conf_interface=${INTERFACE}
fi fi
## VNET requires jib script ## generate the jail configuration file
if [ ! "$(command -v jib)" ]; then if [ -n "${VNET_JAIL}" ]; then
if [ -f /usr/share/examples/jails/jib ] && [ ! -f /usr/local/bin/jib ]; then generate_vnet_jail_conf
install -m 0544 /usr/share/examples/jails/jib /usr/local/bin/jib else
generate_jail_conf
fi
fi
## using relative paths here
## 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}"
if [ -n "${INTERFACE}" ]; then
echo -e "${COLOR_GREEN}INTERFACE: ${INTERFACE}.${COLOR_RESET}"
fi
echo -e "${COLOR_GREEN}RELEASE: ${RELEASE}.${COLOR_RESET}"
echo
if [ -z "${THICK_JAIL}" ]; then
LINK_LIST="bin boot lib libexec rescue sbin usr/bin usr/include usr/lib usr/lib32 usr/libdata usr/libexec usr/sbin usr/share usr/src"
for _link in ${LINK_LIST}; do
ln -sf /.bastille/${_link} ${_link}
done
fi
if [ -z "${THICK_JAIL}" ]; then
## rw
## copy only required files for thin jails
FILE_LIST=".cshrc .profile COPYRIGHT dev etc media mnt net proc root tmp var usr/obj usr/tests"
for files in ${FILE_LIST}; do
if [ -f "${bastille_releasesdir}/${RELEASE}/${files}" ] || [ -d "${bastille_releasesdir}/${RELEASE}/${files}" ]; then
cp -a "${bastille_releasesdir}/${RELEASE}/${files}" "${bastille_jail_path}/${files}"
if [ "$?" -ne 0 ]; then
## notify and clean stale files/directories
bastille destroy "${NAME}"
error_notify "${COLOR_RED}Failed to copy release files, please retry create!${COLOR_RESET}"
fi
fi
done
else
echo -e "${COLOR_GREEN}Creating a thickjail, this may take a while...${COLOR_RESET}"
if [ "${bastille_zfs_enable}" = "YES" ]; then
if [ -n "${bastille_zfs_zpool}" ]; then
## perform release base replication
## sane bastille zfs options
ZFS_OPTIONS=$(echo ${bastille_zfs_options} | sed 's/-o//g')
## take a temp snapshot of the base release
SNAP_NAME="bastille-$(date +%Y-%m-%d-%H%M%S)"
zfs snapshot "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}"@"${SNAP_NAME}"
## replicate the release base to the new thickjail and set the default mountpoint
zfs send -R "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}"@"${SNAP_NAME}" | \
zfs receive "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root"
zfs set ${ZFS_OPTIONS} mountpoint=none "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root"
zfs inherit mountpoint "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root"
## cleanup temp snapshots initially
zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}"@"${SNAP_NAME}"
zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root"@"${SNAP_NAME}"
if [ "$?" -ne 0 ]; then
## notify and clean stale files/directories
bastille destroy "${NAME}"
error_notify "${COLOR_RED}Failed release base replication, please retry create!${COLOR_RESET}"
fi
fi
else
## copy all files for thick jails
cp -a "${bastille_releasesdir}/${RELEASE}/" "${bastille_jail_path}"
if [ "$?" -ne 0 ]; then
## notify and clean stale files/directories
bastille destroy "${NAME}"
error_notify "${COLOR_RED}Failed to copy release files, please retry create!${COLOR_RESET}"
fi fi
fi fi
fi fi
fi
## resolv.conf (default: copy from host) ## create home directory if missing
if [ ! -f "${bastille_jail_resolv_conf}" ]; then if [ ! -d "${bastille_jail_path}/usr/home" ]; then
cp -L "${bastille_resolv_conf}" "${bastille_jail_resolv_conf}" mkdir -p "${bastille_jail_path}/usr/home"
fi fi
## link home properly
if [ ! -L "home" ]; then
ln -s usr/home home
fi
## TZ: configurable (default: Etc/UTC) ## rc.conf
ln -s "/usr/share/zoneinfo/${bastille_tzdata}" etc/localtime ## + 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"
## 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
## 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
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
} }
# Handle special-case commands first. # Handle special-case commands first.
@@ -372,6 +403,7 @@ if echo "$3" | grep '@'; then
fi fi
## reset this options ## reset this options
EMPTY_JAIL=""
THICK_JAIL="" THICK_JAIL=""
VNET_JAIL="" VNET_JAIL=""
@@ -384,6 +416,10 @@ if [ "${1}" = "-T" -o "${1}" = "--thick" -o "${1}" = "thick" ] && \
else else
## handle single options ## handle single options
case "${1}" in case "${1}" in
-E|--empty|empty)
shift
EMPTY_JAIL="1"
;;
-T|--thick|thick) -T|--thick|thick)
shift shift
THICK_JAIL="1" THICK_JAIL="1"
@@ -404,64 +440,86 @@ RELEASE="$2"
IP="$3" IP="$3"
INTERFACE="$4" INTERFACE="$4"
if [ $# -gt 4 ] || [ $# -lt 3 ]; then if [ -n "${EMPTY_JAIL}" ]; then
usage if [ $# -ne 1 ]; then
usage
fi
else
if [ $# -gt 4 ] || [ $# -lt 3 ]; then
usage
fi
fi fi
## don't allow for dots(.) in container names ## validate jail name
if echo "${NAME}" | grep -q "[.]"; then if [ -n "${NAME}" ]; then
echo -e "${COLOR_RED}Container names may not contain a dot(.)!${COLOR_RESET}" validate_name
exit 1
fi fi
## verify release if [ -z "${EMPTY_JAIL}" ]; then
case "${RELEASE}" in ## verify release
*-RELEASE|*-release|*-RC1|*-rc1|*-RC2|*-rc2) case "${RELEASE}" in
## check for FreeBSD releases name *-RELEASE|*-release|*-RC1|*-rc1|*-RC2|*-rc2)
NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '^([1-9]{2,2})\.[0-9](-RELEASE|-RC[1-2])$' | tr '[:lower:]' '[:upper:]') ## check for FreeBSD releases name
validate_release NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '^([1-9]{2,2})\.[0-9](-RELEASE|-RC[1-2])$' | tr '[:lower:]' '[:upper:]')
;; validate_release
*-stable-LAST|*-STABLE-last|*-stable-last|*-STABLE-LAST) ;;
## check for HardenedBSD releases name(previous infrastructure) *-stable-LAST|*-STABLE-last|*-stable-last|*-STABLE-LAST)
NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '^([1-9]{2,2})(-stable-last)$' | sed 's/STABLE/stable/g' | sed 's/last/LAST/g') ## check for HardenedBSD releases name(previous infrastructure)
validate_release NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '^([1-9]{2,2})(-stable-last)$' | sed 's/STABLE/stable/g' | sed 's/last/LAST/g')
;; validate_release
*-stable-build-[0-9]*|*-STABLE-BUILD-[0-9]*) ;;
## check for HardenedBSD(specific stable build releases) *-stable-build-[0-9]*|*-STABLE-BUILD-[0-9]*)
NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '([0-9]{1,2})(-stable-build)-([0-9]{1,3})$' | sed 's/BUILD/build/g' | sed 's/STABLE/stable/g') ## check for HardenedBSD(specific stable build releases)
validate_release NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '([0-9]{1,2})(-stable-build)-([0-9]{1,3})$' | sed 's/BUILD/build/g' | sed 's/STABLE/stable/g')
;; validate_release
*-stable-build-latest|*-stable-BUILD-LATEST|*-STABLE-BUILD-LATEST) ;;
## check for HardenedBSD(latest stable build release) *-stable-build-latest|*-stable-BUILD-LATEST|*-STABLE-BUILD-LATEST)
NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '([0-9]{1,2})(-stable-build-latest)$' | sed 's/STABLE/stable/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g') ## check for HardenedBSD(latest stable build release)
validate_release NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '([0-9]{1,2})(-stable-build-latest)$' | sed 's/STABLE/stable/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g')
;; validate_release
current-build-[0-9]*|CURRENT-BUILD-[0-9]*) ;;
## check for HardenedBSD(specific current build releases) current-build-[0-9]*|CURRENT-BUILD-[0-9]*)
NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '(current-build)-([0-9]{1,3})' | sed 's/BUILD/build/g' | sed 's/CURRENT/current/g') ## check for HardenedBSD(specific current build releases)
validate_release NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '(current-build)-([0-9]{1,3})' | sed 's/BUILD/build/g' | sed 's/CURRENT/current/g')
;; validate_release
current-build-latest|current-BUILD-LATEST|CURRENT-BUILD-LATEST) ;;
## check for HardenedBSD(latest current build release) current-build-latest|current-BUILD-LATEST|CURRENT-BUILD-LATEST)
NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '(current-build-latest)' | sed 's/CURRENT/current/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g') ## check for HardenedBSD(latest current build release)
validate_release NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '(current-build-latest)' | sed 's/CURRENT/current/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g')
;; validate_release
*) ;;
echo -e "${COLOR_RED}Unknown Release.${COLOR_RESET}" *)
usage echo -e "${COLOR_RED}Unknown Release.${COLOR_RESET}"
;; usage
esac ;;
esac
## check for name/root/.bastille ## check for name/root/.bastille
if [ -d "${bastille_jailsdir}/${NAME}/root/.bastille" ]; then if [ -d "${bastille_jailsdir}/${NAME}/root/.bastille" ]; then
echo -e "${COLOR_RED}Jail: ${NAME} already created. ${NAME}/root/.bastille exists.${COLOR_RESET}" error_notify "${COLOR_RED}Jail: ${NAME} already created. ${NAME}/root/.bastille exists.${COLOR_RESET}"
exit 1 fi
fi
## check for required release ## check for required release
if [ ! -d "${bastille_releasesdir}/${RELEASE}" ]; then if [ ! -d "${bastille_releasesdir}/${RELEASE}" ]; then
echo -e "${COLOR_RED}Release must be bootstrapped first; see 'bastille bootstrap'.${COLOR_RESET}" error_notify "${COLOR_RED}Release must be bootstrapped first; see 'bastille bootstrap'.${COLOR_RESET}"
exit 1 fi
## check if ip address is valid
if [ -n "${IP}" ]; then
validate_ip
else
usage
fi
## check if interface is valid
if [ -n "${INTERFACE}" ]; then
validate_netif
validate_netconf
else
validate_netconf
fi
else
echo -e "${COLOR_GREEN}Creating empty jail: ${NAME}.${COLOR_RESET}"
fi fi
## check if a running jail matches name or already exist ## check if a running jail matches name or already exist
@@ -469,19 +527,4 @@ if [ -n "${NAME}" ]; then
running_jail running_jail
fi fi
## check if ip address is valid
if [ -n "${IP}" ]; then
validate_ip
else
usage
fi
## check if interface is valid
if [ -n "${INTERFACE}" ]; then
validate_netif
validate_netconf
else
validate_netconf
fi
create_jail "${NAME}" "${RELEASE}" "${IP}" "${INTERFACE}" create_jail "${NAME}" "${RELEASE}" "${IP}" "${INTERFACE}"

View File

@@ -109,9 +109,9 @@ update_jailconf() {
if [ -f "${JAIL_CONFIG}" ]; then if [ -f "${JAIL_CONFIG}" ]; then
if ! grep -qw "path = ${bastille_jailsdir}/${TARGET_TRIM}/root;" "${JAIL_CONFIG}"; then if ! grep -qw "path = ${bastille_jailsdir}/${TARGET_TRIM}/root;" "${JAIL_CONFIG}"; then
echo -e "${COLOR_GREEN}Updating jail.conf...${COLOR_RESET}" echo -e "${COLOR_GREEN}Updating jail.conf...${COLOR_RESET}"
sed -i '' "s|exec.consolelog.*= .*;|exec.consolelog = ${bastille_logsdir}/${TARGET_TRIM}_console.log;|" "${JAIL_CONFIG}" 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|path.*=.*;|path = ${bastille_jailsdir}/${TARGET_TRIM}/root;|" "${JAIL_CONFIG}"
sed -i '' "s|mount.fstab.*= .*;|mount.fstab = ${bastille_jailsdir}/${TARGET_TRIM}/fstab;|" "${JAIL_CONFIG}" sed -i '' "s|mount.fstab.*=.*;|mount.fstab = ${bastille_jailsdir}/${TARGET_TRIM}/fstab;|" "${JAIL_CONFIG}"
fi fi
fi fi
} }

View File

@@ -42,6 +42,14 @@ error_notify() {
exit 1 exit 1
} }
validate_name() {
local NAME_VERIFY=${NEWNAME}
local NAME_SANITY=$(echo "${NAME_VERIFY}" | tr -c -d 'a-zA-Z0-9-_')
if [ "${NAME_VERIFY}" != "${NAME_SANITY}" ]; then
error_notify "${COLOR_RED}Container names may not contain special characters!${COLOR_RESET}"
fi
}
# Handle special-case commands first # Handle special-case commands first
case "$1" in case "$1" in
help|-h|--help) help|-h|--help)
@@ -57,21 +65,16 @@ TARGET="${1}"
NEWNAME="${2}" NEWNAME="${2}"
shift shift
if echo "${NEWNAME}" | grep -q "[.]"; then
echo -e "${COLOR_RED}Container names may not contain a dot(.)!${COLOR_RESET}"
exit 1
fi
update_jailconf() { update_jailconf() {
# Update jail.conf # Update jail.conf
JAIL_CONFIG="${bastille_jailsdir}/${NEWNAME}/jail.conf" JAIL_CONFIG="${bastille_jailsdir}/${NEWNAME}/jail.conf"
if [ -f "${JAIL_CONFIG}" ]; then if [ -f "${JAIL_CONFIG}" ]; then
if ! grep -qw "path = ${bastille_jailsdir}/${NEWNAME}/root;" "${JAIL_CONFIG}"; then if ! grep -qw "path = ${bastille_jailsdir}/${NEWNAME}/root;" "${JAIL_CONFIG}"; then
sed -i '' "s|host.hostname = ${TARGET};|host.hostname = ${NEWNAME};|" "${JAIL_CONFIG}" sed -i '' "s|host.hostname.*=.*${TARGET};|host.hostname = ${NEWNAME};|" "${JAIL_CONFIG}"
sed -i '' "s|exec.consolelog = .*;|exec.consolelog = ${bastille_logsdir}/${NEWNAME}_console.log;|" "${JAIL_CONFIG}" sed -i '' "s|exec.consolelog.*=.*;|exec.consolelog = ${bastille_logsdir}/${NEWNAME}_console.log;|" "${JAIL_CONFIG}"
sed -i '' "s|path = .*;|path = ${bastille_jailsdir}/${NEWNAME}/root;|" "${JAIL_CONFIG}" sed -i '' "s|path.*=.*;|path = ${bastille_jailsdir}/${NEWNAME}/root;|" "${JAIL_CONFIG}"
sed -i '' "s|mount.fstab = .*;|mount.fstab = ${bastille_jailsdir}/${NEWNAME}/fstab;|" "${JAIL_CONFIG}" sed -i '' "s|mount.fstab.*=.*;|mount.fstab = ${bastille_jailsdir}/${NEWNAME}/fstab;|" "${JAIL_CONFIG}"
sed -i '' "s|${TARGET} {|${NEWNAME} {|" "${JAIL_CONFIG}" sed -i '' "s|${TARGET}.*{|${NEWNAME} {|" "${JAIL_CONFIG}"
fi fi
fi fi
} }
@@ -97,14 +100,33 @@ change_name() {
if [ -d "${bastille_jailsdir}/${TARGET}" ]; then if [ -d "${bastille_jailsdir}/${TARGET}" ]; then
echo -e "${COLOR_GREEN}Attempting to rename '${TARGET}' to ${NEWNAME}...${COLOR_RESET}" echo -e "${COLOR_GREEN}Attempting to rename '${TARGET}' to ${NEWNAME}...${COLOR_RESET}"
if [ "${bastille_zfs_enable}" = "YES" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then
if [ -n "${bastille_zfs_zpool}" ]; then if [ -n "${bastille_zfs_zpool}" ] && [ -n "${bastille_zfs_prefix}" ]; then
# Rename ZFS dataset and mount points accordingly # Check and rename container ZFS dataset accordingly
zfs rename "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NEWNAME}" # Perform additional checks in case of non-zfs existing containers
zfs set mountpoint="${bastille_jailsdir}/${NEWNAME}/root" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NEWNAME}/root" if zfs list | grep -qw "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}"; then
zfs rename "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NEWNAME}"
else
# Check and rename container directory instead
if ! zfs list | grep -qw "jails/${TARGET}$"; then
mv "${bastille_jailsdir}/${TARGET}" "${bastille_jailsdir}/${NEWNAME}"
fi
fi
fi fi
else else
# Just rename the jail directory # Check if container is a zfs/dataset before rename attempt
mv "${bastille_jailsdir}/${TARGET}" "${bastille_jailsdir}/${NEWNAME}" # Perform additional checks in case of bastille.conf miss-configuration
if zfs list | grep -qw "jails/${TARGET}$"; then
ZFS_DATASET_ORIGIN=$(zfs list | grep -w "jails/${TARGET}$" | awk '{print $1}')
ZFS_DATASET_TARGET=$(echo "${ZFS_DATASET_ORIGIN}" | sed "s|\/${TARGET}||")
if [ -n "${ZFS_DATASET_ORIGIN}" ] && [ -n "${ZFS_DATASET_TARGET}" ]; then
zfs rename "${ZFS_DATASET_ORIGIN}" "${ZFS_DATASET_TARGET}/${NEWNAME}"
else
error_notify "${COLOR_RED}Can't determine the zfs origin path of '${TARGET}'.${COLOR_RESET}"
fi
else
# Just rename the jail directory
mv "${bastille_jailsdir}/${TARGET}" "${bastille_jailsdir}/${NEWNAME}"
fi
fi fi
else else
error_notify "${COLOR_RED}${TARGET} not found. See bootstrap.${COLOR_RESET}" error_notify "${COLOR_RED}${TARGET} not found. See bootstrap.${COLOR_RESET}"
@@ -114,10 +136,7 @@ change_name() {
update_jailconf update_jailconf
update_fstab update_fstab
# Remove the old jail directory if exist # Check exit status and notify
if [ -d "${bastille_jailsdir}/${TARGET}" ]; then
rm -r "${bastille_jailsdir}/${TARGET}"
fi
if [ "$?" -ne 0 ]; then if [ "$?" -ne 0 ]; then
error_notify "${COLOR_RED}An error has occurred while attempting to rename '${TARGET}'.${COLOR_RESET}" error_notify "${COLOR_RED}An error has occurred while attempting to rename '${TARGET}'.${COLOR_RESET}"
else else
@@ -125,9 +144,16 @@ change_name() {
fi fi
} }
# Check if container is running ## check if a running jail matches name or already exist
if [ -n "$(jls name | awk "/^${TARGET}$/")" ]; then if [ "$(jls name | awk "/^${TARGET}$/")" ]; then
error_notify "${COLOR_RED}${TARGET} is running, See 'bastille stop'.${COLOR_RESET}" error_notify "${COLOR_RED}Warning: ${TARGET} is running or the name does match.${COLOR_RESET}"
elif [ -d "${bastille_jailsdir}/${NEWNAME}" ]; then
error_notify "${COLOR_RED}Jail: ${NEWNAME} already exist.${COLOR_RESET}"
fi
## validate jail name
if [ -n "${NEWNAME}" ]; then
validate_name
fi fi
change_name change_name