Merge pull request #55 from JRGTH/master

Add "thick" container type, improve container name matching, validate network configuration
This commit is contained in:
Christer Edwards
2019-11-20 16:33:19 -07:00
committed by GitHub
6 changed files with 186 additions and 62 deletions

View File

@@ -29,25 +29,25 @@ Usage:
bastille command [ALL|glob] [args] bastille command [ALL|glob] [args]
Available Commands: Available Commands:
bootstrap Bootstrap a FreeBSD release for jail base. bootstrap Bootstrap a FreeBSD release for container base.
cmd Execute arbitrary command on targeted jail(s). cmd Execute arbitrary command on targeted container(s).
console Console into a running jail. console Console into a running container.
cp cp(1) files from host to targeted jail(s). cp cp(1) files from host to targeted container(s).
create Create a new jail. create Create a new thin container or a thick container if -T|--thick option specified.
destroy Destroy a stopped jail. destroy Destroy a stopped container or a FreeBSD release.
help Help about any command help Help about any command
htop Interactive process viewer (requires htop). htop Interactive process viewer (requires htop).
list List jails (running and stopped). list List containers (running and stopped).
pkg Manipulate binary packages within targeted jail(s). See pkg(8). pkg Manipulate binary packages within targeted container(s). See pkg(8).
restart Restart a running jail. restart Restart a running container.
service Manage services within targeted jail(s). service Manage services within targeted jail(s).
start Start a stopped jail. start Start a stopped container.
stop Stop a running jail. stop Stop a running container.
sysrc Safely edit rc files within targeted jail(s). sysrc Safely edit rc files within targeted container(s).
template Apply Bastille template to running jail(s). template Apply file templates to targeted jail(s).
top Display and update information about the top(1) cpu processes. top Display and update information about the top(1) cpu processes.
update Update jail base -pX release. update Update container base -pX release.
upgrade Upgrade jail release to X.Y-RELEASE. upgrade Upgrade container release to X.Y-RELEASE.
verify Compare release against a "known good" index. verify Compare release against a "known good" index.
zfs Manage (get|set) zfs attributes on targeted jail(s). zfs Manage (get|set) zfs attributes on targeted jail(s).
@@ -63,7 +63,11 @@ framework. This release is still considered beta.
Network Requirements Network Requirements
==================== ====================
In order to segregate jails from the network and from the world, Bastille Several networking options can be performed regarding the user needs.
Basic jails can support IP alias networking, where the IP address is assigned
to the host interface and used by the jail, generally known as "shared IP" based jails.
However, in order to segregate jails from the network and from the world, Bastille
attaches jails to a loopback interface only. The host system then acts as attaches jails to a loopback interface only. The host system then acts as
the firewall, permitting and denying traffic as needed. the firewall, permitting and denying traffic as needed.
@@ -253,6 +257,12 @@ IP: 10.17.89.10.
This command will create a 12.0-RELEASE jail assigning the 10.17.89.10 ip This command will create a 12.0-RELEASE jail assigning the 10.17.89.10 ip
address to the new system. address to the new system.
Optionally `bastille create [ -T | --thick ]` will create a self contained Thickjail system instead.
```shell
ishmael ~ # bastille create -T folsom 12.0-RELEASE 10.17.89.10
```
I recommend using private (rfc1918) ip address ranges for your jails. I recommend using private (rfc1918) ip address ranges for your jails.
These ranges include: These ranges include:

View File

@@ -47,7 +47,6 @@ bastille_root_check
. /usr/local/etc/bastille/bastille.conf . /usr/local/etc/bastille/bastille.conf
. /usr/local/share/bastille/colors.pre.sh . /usr/local/share/bastille/colors.pre.sh
## bastille_prefix should be 0750 ## bastille_prefix should be 0750
## this restricts file system access to privileged users ## this restricts file system access to privileged users
bastille_perms_check() { bastille_perms_check() {
@@ -64,7 +63,6 @@ bastille_perms_check() {
bastille_perms_check bastille_perms_check
## we only load the config if root_check passes ## we only load the config if root_check passes
. /usr/local/etc/bastille/bastille.conf . /usr/local/etc/bastille/bastille.conf
@@ -84,7 +82,7 @@ Available Commands:
cmd Execute arbitrary command on targeted container(s). cmd Execute arbitrary command on targeted container(s).
console Console into a running container. console Console into a running container.
cp cp(1) files from host to targeted container(s). cp cp(1) files from host to targeted container(s).
create Create a new container. create Create a new thin container or a thick container if -T|--thick option specified.
destroy Destroy a stopped container or a FreeBSD release. destroy Destroy a stopped container or a FreeBSD release.
help Help about any command help Help about any command
htop Interactive process viewer (requires htop). htop Interactive process viewer (requires htop).

View File

@@ -32,7 +32,7 @@
. /usr/local/etc/bastille/bastille.conf . /usr/local/etc/bastille/bastille.conf
usage() { usage() {
echo -e "${COLOR_RED}Usage: bastille create name release ip | interface.${COLOR_RESET}" echo -e "${COLOR_RED}Usage: bastille create [option] name release ip | interface.${COLOR_RESET}"
exit 1 exit 1
} }
@@ -70,6 +70,23 @@ validate_netif() {
fi fi
} }
validate_netconf() {
if [ ! -z "${bastille_jail_external}" ]; then
break
elif [ ! -z ${bastille_jail_loopback} ] && [ -z ${bastille_jail_external} ]; then
if [ -z "${bastille_jail_interface}" ]; then
echo -e "${COLOR_RED}Invalid network configuration.${COLOR_RESET}"
exit 1
fi
elif [ -z ${bastille_jail_loopback} ] && [ ! -z ${bastille_jail_interface} ]; then
echo -e "${COLOR_RED}Invalid network configuration.${COLOR_RESET}"
exit 1
elif [ -z ${bastille_jail_external} ]; then
echo -e "${COLOR_RED}Invalid network configuration.${COLOR_RESET}"
exit 1
fi
}
create_jail() { create_jail() {
bastille_jail_base="${bastille_jailsdir}/${NAME}/root/.bastille" ## dir bastille_jail_base="${bastille_jailsdir}/${NAME}/root/.bastille" ## dir
bastille_jail_template="${bastille_jailsdir}/${NAME}/root/.template" ## dir bastille_jail_template="${bastille_jailsdir}/${NAME}/root/.template" ## dir
@@ -85,7 +102,9 @@ create_jail() {
if [ ! -z "${bastille_zfs_zpool}" ]; then if [ ! -z "${bastille_zfs_zpool}" ]; then
## create required zfs datasets ## create required zfs datasets
zfs create ${bastille_zfs_options} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME} 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 if [ -z "${THICK_JAIL}" ]; then
zfs create ${bastille_zfs_options} -o mountpoint=${bastille_jailsdir}/${NAME}/root ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root
fi
fi fi
else else
mkdir -p "${bastille_jailsdir}/${NAME}" mkdir -p "${bastille_jailsdir}/${NAME}"
@@ -94,7 +113,13 @@ create_jail() {
if [ ! -d "${bastille_jail_base}" ]; then if [ ! -d "${bastille_jail_base}" ]; then
mkdir -p "${bastille_jail_base}" mkdir -p "${bastille_jail_base}"
fi
if [ ! -d "${bastille_jail_path}/usr/home" ]; then
mkdir -p "${bastille_jail_path}/usr/home" mkdir -p "${bastille_jail_path}/usr/home"
fi
if [ ! -d "${bastille_jail_path}/usr/local" ]; then
mkdir -p "${bastille_jail_path}/usr/local" mkdir -p "${bastille_jail_path}/usr/local"
fi fi
@@ -103,7 +128,11 @@ create_jail() {
fi fi
if [ ! -f "${bastille_jail_fstab}" ]; then if [ ! -f "${bastille_jail_fstab}" ]; then
echo -e "${bastille_releasesdir}/${RELEASE} ${bastille_jail_base} nullfs ro 0 0" > ${bastille_jail_fstab} 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 fi
if [ ! -f "${bastille_jail_conf}" ]; then if [ ! -f "${bastille_jail_conf}" ]; then
@@ -116,14 +145,28 @@ create_jail() {
if [ ! -z ${INTERFACE} ]; then if [ ! -z ${INTERFACE} ]; then
local bastille_jail_conf_interface=${INTERFACE} local bastille_jail_conf_interface=${INTERFACE}
fi fi
echo -e "interface = ${bastille_jail_conf_interface};\nhost.hostname = ${NAME};\nexec.consolelog = \
${bastille_jail_log};\npath = ${bastille_jail_path};\nip6 = \ ## generate the jail configuration file
disable;\nsecurelevel = 2;\ndevfs_ruleset = 4;\nenforce_statfs = \ cat << EOF > ${bastille_jail_conf}
2;\nexec.start = '/bin/sh /etc/rc';\nexec.stop = '/bin/sh \ interface = ${bastille_jail_conf_interface};
/etc/rc.shutdown';\nexec.clean;\nmount.devfs;\nmount.fstab = \ host.hostname = ${NAME};
${bastille_jail_fstab};\n\n${NAME} {\n\tip4.addr = ${IP};\n}" > \ exec.consolelog = ${bastille_jail_log};
${bastille_jail_conf} path = ${bastille_jail_path};
fi ip6 = disable;
securelevel = 2;
devfs_ruleset = 4;
enforce_statfs = 2;
exec.start = '/bin/sh /etc/rc';
exec.stop = '/bin/sh /etc/rc.shutdown';
exec.clean;
mount.devfs;
mount.fstab = ${bastille_jail_fstab};
${NAME} {
ip4.addr = ${IP};
}
EOF
fi
## using relative paths here ## using relative paths here
## MAKE SURE WE'RE IN THE RIGHT PLACE ## MAKE SURE WE'RE IN THE RIGHT PLACE
@@ -137,28 +180,70 @@ fi
echo -e "${COLOR_GREEN}RELEASE: ${RELEASE}.${COLOR_RESET}" echo -e "${COLOR_GREEN}RELEASE: ${RELEASE}.${COLOR_RESET}"
echo echo
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 if [ -z "${THICK_JAIL}" ]; then
ln -sf /.bastille/${_link} ${_link} 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
done ln -sf /.bastille/${_link} ${_link}
done
fi
## link home properly ## link home properly
ln -s usr/home home ln -s usr/home home
## rw if [ -z "${THICK_JAIL}" ]; then
cp -a "${bastille_releasesdir}/${RELEASE}/.cshrc" "${bastille_jail_path}" ## rw
cp -a "${bastille_releasesdir}/${RELEASE}/.profile" "${bastille_jail_path}" ## copy only required files for thin jails
cp -a "${bastille_releasesdir}/${RELEASE}/COPYRIGHT" "${bastille_jail_path}" FILE_LIST=".cshrc .profile COPYRIGHT dev etc media mnt net proc root tmp var usr/obj usr/tests"
cp -a "${bastille_releasesdir}/${RELEASE}/dev" "${bastille_jail_path}" for files in ${FILE_LIST}; do
cp -a "${bastille_releasesdir}/${RELEASE}/etc" "${bastille_jail_path}" if [ -f "${bastille_releasesdir}/${RELEASE}/${files}" ] || [ -d "${bastille_releasesdir}/${RELEASE}/${files}" ]; then
cp -a "${bastille_releasesdir}/${RELEASE}/media" "${bastille_jail_path}" cp -a "${bastille_releasesdir}/${RELEASE}/${files}" "${bastille_jail_path}/${files}"
cp -a "${bastille_releasesdir}/${RELEASE}/mnt" "${bastille_jail_path}" if [ $? -ne 0 ]; then
if [ "${RELEASE}" == "11.2-RELEASE" ]; then cp -a "${bastille_releasesdir}/${RELEASE}/net" "${bastille_jail_path}"; fi ## notify and clean stale files/directories
cp -a "${bastille_releasesdir}/${RELEASE}/proc" "${bastille_jail_path}" echo -e "${COLOR_RED}Failed to copy release files, please retry create!${COLOR_RESET}"
cp -a "${bastille_releasesdir}/${RELEASE}/root" "${bastille_jail_path}" bastille destroy ${NAME}
cp -a "${bastille_releasesdir}/${RELEASE}/tmp" "${bastille_jail_path}" exit 1
cp -a "${bastille_releasesdir}/${RELEASE}/var" "${bastille_jail_path}" fi
cp -a "${bastille_releasesdir}/${RELEASE}/usr/obj" "${bastille_jail_path}" fi
if [ "${RELEASE}" == "11.2-RELEASE" ]; then cp -a "${bastille_releasesdir}/${RELEASE}/usr/tests" "${bastille_jail_path}"; fi done
else
echo -e "${COLOR_GREEN}Creating a thickjail, this may take a while...${COLOR_RESET}"
if [ "${bastille_zfs_enable}" = "YES" ]; then
if [ ! -z "${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=${bastille_jailsdir}/${NAME}/root ${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
## rc.conf ## rc.conf
## + syslogd_flags="-ss" ## + syslogd_flags="-ss"
@@ -188,19 +273,47 @@ help|-h|--help)
;; ;;
esac esac
if [ $# -gt 4 ] || [ $# -lt 3 ]; then
usage
fi
if [ $(echo $3 | grep '@' ) ]; then if [ $(echo $3 | grep '@' ) ]; then
BASTILLE_JAIL_IP=$(echo $3 | awk -F@ '{print $2}') BASTILLE_JAIL_IP=$(echo $3 | awk -F@ '{print $2}')
BASTILLE_JAIL_INTERFACES=$( echo $3 | awk -F@ '{print $1}') BASTILLE_JAIL_INTERFACES=$( echo $3 | awk -F@ '{print $1}')
fi fi
NAME="$1" TYPE="$1"
RELEASE="$2" NAME="$2"
IP="$3" RELEASE="$3"
INTERFACE="$4" IP="$4"
INTERFACE="$5"
## handle additional options
case "${TYPE}" in
-T|--thick|thick)
if [ $# -gt 5 ] || [ $# -lt 4 ]; then
usage
fi
THICK_JAIL="0"
break
;;
-*)
echo -e "${COLOR_RED}Unknown Option.${COLOR_RESET}"
usage
;;
*)
if [ $# -gt 4 ] || [ $# -lt 3 ]; then
usage
fi
THICK_JAIL=""
NAME="$1"
RELEASE="$2"
IP="$3"
INTERFACE="$4"
;;
esac
## don't allow for dots(.) in container names
if [ $(echo "${NAME}" | grep "[.]") ]; then
echo -e "${COLOR_RED}Container names may not contain a dot(.)!${COLOR_RESET}"
exit 1
fi
## verify release ## verify release
case "${RELEASE}" in case "${RELEASE}" in
@@ -257,6 +370,8 @@ fi
## check if interface is valid ## check if interface is valid
if [ ! -z ${INTERFACE} ]; then if [ ! -z ${INTERFACE} ]; then
validate_netif validate_netif
else
validate_netconf
fi fi
create_jail ${NAME} ${RELEASE} ${IP} ${INTERFACE} create_jail ${NAME} ${RELEASE} ${IP} ${INTERFACE}

View File

@@ -40,7 +40,7 @@ destroy_jail() {
bastille_jail_base="${bastille_jailsdir}/${NAME}" ## dir bastille_jail_base="${bastille_jailsdir}/${NAME}" ## dir
bastille_jail_log="${bastille_logsdir}/${NAME}_console.log" ## file bastille_jail_log="${bastille_logsdir}/${NAME}_console.log" ## file
if [ $(jls name | grep ${NAME}) ]; then if [ $(jls name | grep -w "${NAME}") ]; then
echo -e "${COLOR_RED}Jail running.${COLOR_RESET}" echo -e "${COLOR_RED}Jail running.${COLOR_RESET}"
echo -e "${COLOR_RED}See 'bastille stop ${NAME}'.${COLOR_RESET}" echo -e "${COLOR_RED}See 'bastille stop ${NAME}'.${COLOR_RESET}"
exit 1 exit 1
@@ -55,9 +55,10 @@ destroy_jail() {
echo -e "${COLOR_GREEN}Deleting Jail: ${NAME}.${COLOR_RESET}" echo -e "${COLOR_GREEN}Deleting Jail: ${NAME}.${COLOR_RESET}"
if [ "${bastille_zfs_enable}" = "YES" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then
if [ ! -z "${bastille_zfs_zpool}" ]; then if [ ! -z "${bastille_zfs_zpool}" ]; then
## remove zfs datasets individually if [ ! -z "${NAME}" ]; then
zfs destroy ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root ## remove jail zfs dataset recursively
zfs destroy ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME} zfs destroy -r ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}
fi
fi fi
fi fi

View File

@@ -51,7 +51,7 @@ if [ "$1" = 'ALL' ]; then
JAILS=$(/usr/local/bin/bastille list jails) JAILS=$(/usr/local/bin/bastille list jails)
fi fi
if [ "$1" != 'ALL' ]; then if [ "$1" != 'ALL' ]; then
JAILS=$(/usr/local/bin/bastille list jails | grep "$1") JAILS=$(/usr/local/bin/bastille list jails | grep -w "$1")
fi fi
for _jail in ${JAILS}; do for _jail in ${JAILS}; do

View File

@@ -51,7 +51,7 @@ if [ "$1" = 'ALL' ]; then
JAILS=$(jls name) JAILS=$(jls name)
fi fi
if [ "$1" != 'ALL' ]; then if [ "$1" != 'ALL' ]; then
JAILS=$(jls name | grep -E "(^|\b)${1}($|\b)") JAILS=$(jls name | grep -w "$1")
fi fi
for _jail in ${JAILS}; do for _jail in ${JAILS}; do