diff --git a/Makefile b/Makefile index 70e6749d..7cb91bee 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,9 @@ uninstall: @echo "Removing Bastille sub-commands" @rm -rvf /usr/local/share/bastille @echo + @echo "removing man page" + @rm -rvf /usr/local/share/man/man1/bastille.1.gz + @echo @echo "removing configuration file" @rm -rvf /usr/local/etc/bastille/bastille.conf.sample @echo diff --git a/README.md b/README.md index 828db65a..eee17376 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,10 @@ -Bastille: Automate Container Security -===================================== +Bastille +======== [Bastille](https://bastillebsd.org/) is an open-source system for automating deployment and management of containerized applications on FreeBSD. Looking for [Bastille Templates](https://gitlab.com/BastilleBSD-Templates/)? - Installation ============ Bastille is available in the official FreeBSD ports tree. @@ -21,7 +20,7 @@ portsnap fetch auto make -C /usr/ports/sysutils/bastille install clean ``` -**Git** +**Git** (bleeding edge / unstable -- primarily for developers) ```shell git clone https://github.com/BastilleBSD/bastille.git cd bastille @@ -50,6 +49,7 @@ Available Commands: cp cp(1) files from host to targeted container(s). create Create a new thin or thick container. destroy Destroy a stopped container or a bootstrapped release. + edit Edit container configuration files (advanced). export Exports a container archive or image. help Help about any command htop Interactive process viewer (requires htop). @@ -293,26 +293,81 @@ IP at container creation. - name - release (bootstrapped) -- ip +- ip (ip4 or ip6) - interface (optional) +**ip4** ```shell -ishmael ~ # bastille create folsom 12.0-RELEASE 10.17.89.10 +ishmael ~ # bastille create folsom 12.1-RELEASE 10.17.89.10 Valid: (10.17.89.10). NAME: folsom. IP: 10.17.89.10. -RELEASE: 12.0-RELEASE. +RELEASE: 12.1-RELEASE. syslogd_flags: -s -> -ss sendmail_enable: NO -> NONE cron_flags: -> -J 60 ``` -This command will create a 12.0-RELEASE container assigning the 10.17.89.10 ip +This command will create a 12.1-RELEASE container assigning the 10.17.89.10 ip address to the new system. +**ip6** +```shell +ishmael ~ # bastille create folsom 12.1-RELEASE fd35:f1fd:2cb6:6c5c::13 +Valid: (fd35:f1fd:2cb6:6c5c::13). + +NAME: folsom. +IP: fd35:f1fd:2cb6:6c5c::13 +RELEASE: 12.1-RELEASE. + +syslogd_flags: -s -> -ss +sendmail_enable: NO -> NONE +cron_flags: -> -J 60 +``` + +This command will create a 12.1-RELEASE container assigning the +fd35:f1fd:2cb6:6c5c::13 ip address to the new system. + +**VNET** +```shell +ishmael ~ # bastille create -V vnetjail 12.1-RELEASE 192.168.87.55/24 em0 +Valid: (192.168.87.55/24). +Valid: (em0). + +NAME: vnettest0. +IP: 192.168.87.55/24. +INTERFACE: em0. +RELEASE: 12.1-RELEASE. + +syslogd_flags: -s -> -ss +sendmail_enable: NO -> NONE +cron_flags: -> -J 60 +ifconfig_e0b_bastille0_name: -> vnet0 +ifconfig_vnet0: -> inet 192.168.87.55/24 +``` + +This command will create a 12.1-RELEASE container assigning the +192.168.87.55/24 ip address to the new system. + +VNET-enabled containers are attached to a virtual bridge interface for +connectivity. This bridge interface is defined by the interface argument in the +create command (in this case, em0). + +VNET also requires a custom `devfs` ruleset. Create the file as needed on the host system: + +**/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 +``` + Optionally `bastille create [ -T | --thick ]` will create a container with a private base. This is sometimes referred to as a "thick" container (whereas the shared base container is a "thin"). @@ -608,7 +663,7 @@ work as expected. This table outlines that order and those requirements: | PLANNED | format | example | |---------|------------------|----------------------------------------------------------------| -| PF | pf rdr entry | rdr pass inet proto tcp from any to any port 80 -> 10.17.89.80 | +| RDR | pf rdr entry | rdr pass inet proto tcp from any to any port 80 -> 10.17.89.80 | | LOG | path | /var/log/nginx/access.log | Note: SYSRC requires NO quotes or that quotes (`"`) be escaped. ie; `\"`) @@ -747,7 +802,7 @@ ishmael ~ # bastille cp ALL /tmp/resolv.conf-cf etc/resolv.conf /tmp/resolv.conf-cf -> /usr/local/bastille/jails/unbound0/root/etc/resolv.conf ``` -bastille-rdr +bastille rdr ------------ `bastille rdr` allows you to configure dynamic rdr rules for your containers @@ -756,7 +811,7 @@ for a private network and have enabled `rdr-anchor 'rdr/*'` in /etc/pf.conf as described in the Networking section). ```shell - # bastille rdr --help + # bastille rdr help Usage: bastille rdr TARGET [clear] | [list] | [tcp ] | [udp ] # bastille rdr dev1 tcp 2001 22 # bastille rdr dev1 list diff --git a/usr/local/bin/bastille b/usr/local/bin/bastille index 07fbc89f..dadc7a63 100755 --- a/usr/local/bin/bastille +++ b/usr/local/bin/bastille @@ -32,7 +32,7 @@ PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin ## root check first. bastille_root_check() { - if [ $(id -u) -ne 0 ]; then + if [ "$(id -u)" -ne 0 ]; then ## so we can make it colorful . /usr/local/share/bastille/colors.pre.sh @@ -69,7 +69,7 @@ bastille_perms_check . /usr/local/etc/bastille/bastille.conf ## version -BASTILLE_VERSION="0.5.20191128" +BASTILLE_VERSION="0.6.20200202" usage() { cat << EOF @@ -87,6 +87,7 @@ Available Commands: cp cp(1) files from host to targeted container(s). create Create a new thin container or a thick container if -T|--thick option specified. destroy Destroy a stopped container or a FreeBSD release. + edit Edit container configuration files (advanced). export Exports a specified container. help Help about any command. htop Interactive process viewer (requires htop). @@ -94,6 +95,7 @@ Available Commands: list List containers (running and stopped). pkg Manipulate binary packages within targeted container(s). See pkg(8). rdr Redirect host port to container port. + rename Rename a container. restart Restart a running container. service Manage services within targeted container(s). start Start a stopped container. @@ -131,13 +133,13 @@ esac # Filter out all non-commands case "${CMD}" in -cmd|convert|cp|create|destroy|export|import|list|pkg|rdr|restart|start|stop|sysrc|template|verify) +bootstrap|cmd|console|convert|cp|create) ;; -update|upgrade) +destroy|edit|export|htop|import|limits|list) ;; -service|console|bootstrap|htop|top) +pkg|rdr|rename|restart|service|start|stop|sysrc) ;; -bootstrap|update|upgrade|zfs) +template|top|update|upgrade|verify|zfs) ;; *) usage @@ -146,12 +148,12 @@ esac SCRIPTPATH="${bastille_sharedir}/${CMD}.sh" if [ -f "${SCRIPTPATH}" ]; then - : ${UMASK:=022} - umask ${UMASK} + : "${UMASK:=022}" + umask "${UMASK}" - : ${SH:=sh} + : "${SH:=sh}" - exec ${SH} "${SCRIPTPATH}" "$@" + exec "${SH}" "${SCRIPTPATH}" "$@" else echo -e "${COLOR_RED}${SCRIPTPATH} not found.${COLOR_RESET}" 1>&2 fi diff --git a/usr/local/share/bastille/bootstrap.sh b/usr/local/share/bastille/bootstrap.sh index c9fb8694..e59d3172 100644 --- a/usr/local/share/bastille/bootstrap.sh +++ b/usr/local/share/bastille/bootstrap.sh @@ -74,6 +74,7 @@ validate_release_url() { echo -e "${COLOR_RED}Unable to fetch MANIFEST, See 'bootstrap urls'.${COLOR_RESET}" exit 1 fi + echo -e "${COLOR_GREEN}Bootstrapping ${PLATFORM_OS} distfiles...${COLOR_RESET}" bootstrap_directories bootstrap_release else @@ -91,85 +92,85 @@ bootstrap_network_interfaces() { fi ## test for required variables -- external - if [ -z "${bastille_jail_loopback}" ] && [ ! -z "${bastille_jail_external}" ]; then + if [ -z "${bastille_jail_loopback}" ] && [ -n "${bastille_jail_external}" ]; then - ## test for existing interface - ifconfig ${bastille_jail_external} 2>&1 >/dev/null - if [ $? = 0 ]; then + ## test for existing interface + ifconfig "${bastille_jail_external}" >/dev/null 2>&1 + if [ "$?" = 0 ]; then - ## create ifconfig alias - ifconfig ${bastille_jail_external} inet ${bastille_jail_addr} alias && \ - echo -e "${COLOR_GREEN}IP alias added to ${bastille_jail_external} successfully.${COLOR_RESET}" - echo + ## create ifconfig alias + ifconfig "${bastille_jail_external}" inet "${bastille_jail_addr}" alias && \ + echo -e "${COLOR_GREEN}IP alias added to ${bastille_jail_external} successfully.${COLOR_RESET}" + echo - ## attempt to ping gateway - echo -e "${COLOR_YELLOW}Attempting to ping default gateway...${COLOR_RESET}" - ping -c3 -t3 -S ${bastille_jail_addr} ${bastille_jail_gateway} - if [ $? = 0 ]; then - echo - echo -e "${COLOR_GREEN}External networking appears functional.${COLOR_RESET}" - echo - else - echo -e "${COLOR_RED}Unable to ping default gateway.${COLOR_RESET}" - fi - fi + ## attempt to ping gateway + echo -e "${COLOR_YELLOW}Attempting to ping default gateway...${COLOR_RESET}" + ping -c3 -t3 -S "${bastille_jail_addr}" "${bastille_jail_gateway}" + if [ "$?" = 0 ]; then + echo + echo -e "${COLOR_GREEN}External networking appears functional.${COLOR_RESET}" + echo + else + echo -e "${COLOR_RED}Unable to ping default gateway.${COLOR_RESET}" + fi + fi fi ## test for required variables -- loopback - if [ -z "${bastille_jail_external}" ] && [ ! -z "${bastille_jail_loopback}" ] && \ - [ ! -z "${bastille_jail_addr}" ]; then + if [ -z "${bastille_jail_external}" ] && [ -n "${bastille_jail_loopback}" ] && \ + [ -n "${bastille_jail_addr}" ]; then - echo -e "${COLOR_GREEN}Detecting...${COLOR_RESET}" - ## test for existing interface - ifconfig ${bastille_jail_interface} >&2 >/dev/null + echo -e "${COLOR_GREEN}Detecting...${COLOR_RESET}" + ## test for existing interface + ifconfig "${bastille_jail_interface}" >&2 >/dev/null - ## if above return code is 1; create interface - if [ $? = 1 ]; then - sysrc ifconfig_${bastille_jail_loopback}_name | grep ${bastille_jail_interface} >&2 >/dev/null - if [ $? = 1 ]; then - echo - echo -e "${COLOR_GREEN}Defining secure loopback interface.${COLOR_RESET}" - sysrc cloned_interfaces+="${bastille_jail_loopback}" && - sysrc ifconfig_${bastille_jail_loopback}_name="${bastille_jail_interface}" - sysrc ifconfig_${bastille_jail_interface}_aliases+="inet ${bastille_jail_addr}/32" + ## if above return code is 1; create interface + if [ "$?" = 1 ]; then + sysrc ifconfig_"${bastille_jail_loopback}"_name | grep "${bastille_jail_interface}" >&2 >/dev/null + if [ "$?" = 1 ]; then + echo + echo -e "${COLOR_GREEN}Defining secure loopback interface.${COLOR_RESET}" + sysrc cloned_interfaces+="${bastille_jail_loopback}" && + sysrc ifconfig_"${bastille_jail_loopback}"_name="${bastille_jail_interface}" + sysrc ifconfig_"${bastille_jail_interface}"_aliases+="inet ${bastille_jail_addr}/32" - ## create and name interface; assign address - echo - echo -e "${COLOR_GREEN}Creating secure loopback interface.${COLOR_RESET}" - ifconfig ${bastille_jail_loopback} create name ${bastille_jail_interface} - ifconfig ${bastille_jail_interface} up - ifconfig ${bastille_jail_interface} inet ${bastille_jail_addr}/32 + ## create and name interface; assign address + echo + echo -e "${COLOR_GREEN}Creating secure loopback interface.${COLOR_RESET}" + ifconfig "${bastille_jail_loopback}" create name "${bastille_jail_interface}" + ifconfig "${bastille_jail_interface}" up + ifconfig "${bastille_jail_interface}" inet "${bastille_jail_addr}/32" - ## reload firewall - pfctl -f /etc/pf.conf + ## reload firewall + pfctl -f /etc/pf.conf - ## look for nat rule for bastille_jail_addr - echo -e "${COLOR_GREEN}Detecting NAT from bastille0 interface...${COLOR_RESET}" - pfctl -s nat | grep nat | grep ${bastille_jail_addr} - if [ $? = 0 ]; then - ## test connectivity; ping from bastille_jail_addr - echo - echo -e "${COLOR_YELLOW}Attempting to ping default gateway...${COLOR_RESET}" - ping -c3 -t3 -S ${bastille_jail_addr} ${bastille_jail_gateway} - if [ $? = 0 ]; then - echo - echo -e "${COLOR_GREEN}Private networking appears functional.${COLOR_RESET}" - echo - else - echo -e "${COLOR_RED}Unable to ping default gateway.${COLOR_RESET}" - echo -e "${COLOR_YELLOW}See https://github.com/BastilleBSD/bastille/blob/master/README.md#etcpfconf.${COLOR_RESET}" - echo -e - fi - else - echo -e "${COLOR_RED}Unable to detect firewall 'nat' rule.${COLOR_RESET}" - echo -e "${COLOR_YELLOW}See https://github.com/BastilleBSD/bastille/blob/master/README.md#etcpfconf.${COLOR_RESET}" - fi - else - echo -e "${COLOR_RED}Interface ${bastille_jail_loopback} already configured; bailing out.${COLOR_RESET}" - fi - else - echo -e "${COLOR_RED}Interface ${bastille_jail_interface} already active; bailing out.${COLOR_RESET}" - fi + ## look for nat rule for bastille_jail_addr + echo -e "${COLOR_GREEN}Detecting NAT from bastille0 interface...${COLOR_RESET}" + pfctl -s nat | grep nat | grep "${bastille_jail_addr}" + if [ "$?" = 0 ]; then + ## test connectivity; ping from bastille_jail_addr + echo + echo -e "${COLOR_YELLOW}Attempting to ping default gateway...${COLOR_RESET}" + ping -c3 -t3 -S "${bastille_jail_addr}" "${bastille_jail_gateway}" + if [ "$?" = 0 ]; then + echo + echo -e "${COLOR_GREEN}Private networking appears functional.${COLOR_RESET}" + echo + else + echo -e "${COLOR_RED}Unable to ping default gateway.${COLOR_RESET}" + echo -e "${COLOR_YELLOW}See https://github.com/BastilleBSD/bastille/blob/master/README.md#etcpfconf.${COLOR_RESET}" + echo -e + fi + else + echo -e "${COLOR_RED}Unable to detect firewall 'nat' rule.${COLOR_RESET}" + echo -e "${COLOR_YELLOW}See https://github.com/BastilleBSD/bastille/blob/master/README.md#etcpfconf.${COLOR_RESET}" + fi + else + echo -e "${COLOR_RED}Interface ${bastille_jail_loopback} already configured; bailing out.${COLOR_RESET}" + fi + else + echo -e "${COLOR_RED}Interface ${bastille_jail_interface} already active; bailing out.${COLOR_RESET}" + fi fi } @@ -179,8 +180,8 @@ bootstrap_directories() { ## ${bastille_prefix} if [ ! -d "${bastille_prefix}" ]; then if [ "${bastille_zfs_enable}" = "YES" ];then - if [ ! -z "${bastille_zfs_zpool}" ]; then - zfs create ${bastille_zfs_options} -o mountpoint=${bastille_prefix} ${bastille_zfs_zpool}/${bastille_zfs_prefix} + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_prefix}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}" fi else mkdir -p "${bastille_prefix}" @@ -191,8 +192,8 @@ bootstrap_directories() { ## ${bastille_backupsdir} if [ ! -d "${bastille_backupsdir}" ]; then if [ "${bastille_zfs_enable}" = "YES" ];then - if [ ! -z "${bastille_zfs_zpool}" ]; then - zfs create ${bastille_zfs_options} -o mountpoint=${bastille_backupsdir} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/backups + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_backupsdir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/backups" fi else mkdir -p "${bastille_backupsdir}" @@ -203,9 +204,9 @@ bootstrap_directories() { ## ${bastille_cachedir} if [ ! -d "${bastille_cachedir}" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then - if [ ! -z "${bastille_zfs_zpool}" ]; then - zfs create ${bastille_zfs_options} -o mountpoint=${bastille_cachedir} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/cache - zfs create ${bastille_zfs_options} -o mountpoint=${bastille_cachedir}/${RELEASE} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/cache/${RELEASE} + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_cachedir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/cache" + 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}" @@ -213,8 +214,8 @@ bootstrap_directories() { ## 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} + if [ -n "${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}" @@ -224,8 +225,8 @@ bootstrap_directories() { ## ${bastille_jailsdir} if [ ! -d "${bastille_jailsdir}" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then - if [ ! -z "${bastille_zfs_zpool}" ]; then - zfs create ${bastille_zfs_options} -o mountpoint=${bastille_jailsdir} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_jailsdir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails" fi else mkdir -p "${bastille_jailsdir}" @@ -235,8 +236,8 @@ bootstrap_directories() { ## ${bastille_logsdir} if [ ! -d "${bastille_logsdir}" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then - if [ ! -z "${bastille_zfs_zpool}" ]; then - zfs create ${bastille_zfs_options} -o mountpoint=${bastille_logsdir} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/logs + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_logsdir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/logs" fi else mkdir -p "${bastille_logsdir}" @@ -246,8 +247,8 @@ bootstrap_directories() { ## ${bastille_templatesdir} if [ ! -d "${bastille_templatesdir}" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then - if [ ! -z "${bastille_zfs_zpool}" ]; then - zfs create ${bastille_zfs_options} -o mountpoint=${bastille_templatesdir} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/templates + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_templatesdir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/templates" fi else mkdir -p "${bastille_templatesdir}" @@ -257,18 +258,19 @@ bootstrap_directories() { ## ${bastille_releasesdir} if [ ! -d "${bastille_releasesdir}" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then - 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} + if [ -n "${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 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} + if [ -n "${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}" @@ -281,9 +283,9 @@ bootstrap_release() { if [ -f "${bastille_releasesdir}/${RELEASE}/COPYRIGHT" ]; then ## check distfiles list and skip existing cached files bastille_bootstrap_archives=$(echo "${bastille_bootstrap_archives}" | sed "s/base//") - bastille_cached_files=$(ls ${bastille_cachedir}/${RELEASE} | grep -v "MANIFEST" | tr -d ".txz") + bastille_cached_files=$(ls "${bastille_cachedir}/${RELEASE}" | grep -v "MANIFEST" | tr -d ".txz") for distfile in ${bastille_cached_files}; do - bastille_bootstrap_archives=$(echo ${bastille_bootstrap_archives} | sed "s/${distfile}//") + bastille_bootstrap_archives=$(echo "${bastille_bootstrap_archives}" | sed "s/${distfile}//") done ## check if release already bootstrapped, else continue bootstrapping @@ -299,48 +301,51 @@ 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 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_GREEN}Extracting ${PLATFORM_OS} ${RELEASE} ${_archive}.txz.${COLOR_RESET}" + 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" + touch "${bastille_releasesdir}/${RELEASE}/usr/share/skel/dot.hushlogin" + else 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_VALIDATION="1" - fi + ## 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_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 + if [ "${FETCH_VALIDATION}" -ne "0" ]; then + ## perform cleanup only for stale/empty directories on failure + if [ "${bastille_zfs_enable}" = "YES" ]; then + if [ -n "${bastille_zfs_zpool}" ]; then + if [ ! "$(ls -A "${bastille_cachedir}/${RELEASE}")" ]; then + zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/cache/${RELEASE}" fi - if [ -d "${bastille_cachedir}/${RELEASE}" ]; then - if [ ! "$(ls -A ${bastille_cachedir}/${RELEASE})" ]; then - rm -rf ${bastille_cachedir}/${RELEASE} - fi + if [ ! "$(ls -A "${bastille_releasesdir}/${RELEASE}")" ]; then + zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}" 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 + 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 + 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 @@ -348,11 +353,11 @@ bootstrap_release() { ## 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) + 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 + rm "${bastille_cachedir}/${RELEASE}/${_archive}.txz" exit 1 else echo -e "${COLOR_GREEN}Validated checksum for ${RELEASE}:${_archive}.txz.${COLOR_RESET}" @@ -363,9 +368,12 @@ bootstrap_release() { ## 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" - if [ $? -ne 0 ]; then + echo -e "${COLOR_GREEN}Extracting ${PLATFORM_OS} ${RELEASE} ${_archive}.txz.${COLOR_RESET}" + 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" + touch "${bastille_releasesdir}/${RELEASE}/usr/share/skel/dot.hushlogin" + else echo -e "${COLOR_RED}Failed to extract ${_archive}.txz.${COLOR_RESET}" exit 1 fi @@ -384,8 +392,8 @@ bootstrap_template() { ## ${bastille_templatesdir} if [ ! -d "${bastille_templatesdir}" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then - if [ ! -z "${bastille_zfs_zpool}" ]; then - zfs create ${bastille_zfs_options} -o mountpoint=${bastille_templatesdir} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/templates + if [ -n "${bastille_zfs_zpool}" ]; then + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_templatesdir}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/templates" fi else mkdir -p "${bastille_templatesdir}" @@ -408,12 +416,12 @@ bootstrap_template() { $(which git) clone "${_url}" "${_template}" ||\ echo -e "${COLOR_RED}Clone unsuccessful.${COLOR_RESET}" elif [ -d "${_template}/.git" ]; then - cd ${_template} && $(which git) pull ||\ + cd "${_template}" && $(which git) pull ||\ echo -e "${COLOR_RED}Template update unsuccessful.${COLOR_RESET}" fi fi - bastille verify ${_user}/${_repo} + bastille verify "${_user}/${_repo}" } HW_MACHINE=$(sysctl hw.machine | awk '{ print $2 }') @@ -426,44 +434,50 @@ case "${1}" in ## check for FreeBSD releases name NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '^([1-9]{2,2})\.[0-9](-RELEASE|-RC[1-2])$' | tr '[:lower:]' '[:upper:]') UPSTREAM_URL="${bastille_url_freebsd}${HW_MACHINE}/${HW_MACHINE_ARCH}/${NAME_VERIFY}" + PLATFORM_OS="FreeBSD" validate_release_url ;; *-stable-LAST|*-STABLE-last|*-stable-last|*-STABLE-LAST) ## check for HardenedBSD releases name(previous infrastructure, keep for reference) - 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') + NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '^([1-9]{2,2})(-stable-last)$' | sed 's/STABLE/stable/g' | sed 's/last/LAST/g') UPSTREAM_URL="${bastille_url_hardenedbsd}${HW_MACHINE}/${HW_MACHINE_ARCH}/hardenedbsd-${NAME_VERIFY}" + PLATFORM_OS="HardenedBSD" validate_release_url ;; *-stable-build-[0-9]*|*-STABLE-BUILD-[0-9]*) ## check for HardenedBSD(specific stable build releases) - NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '([0-9]{1,2})(-stable-build|-STABLE-BUILD)-([0-9]{1,3})$' | sed 's/BUILD/build/g' | sed 's/STABLE/stable/g') - NAME_RELEASE=$(echo ${NAME_VERIFY} | sed 's/-build-[0-9]\{1,2\}//g') - NAME_BUILD=$(echo ${NAME_VERIFY} | sed 's/[0-9]\{1,2\}-stable-//g') + 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') + NAME_RELEASE=$(echo "${NAME_VERIFY}" | sed 's/-build-[0-9]\{1,2\}//g') + NAME_BUILD=$(echo "${NAME_VERIFY}" | sed 's/[0-9]\{1,2\}-stable-//g') UPSTREAM_URL="${bastille_url_hardenedbsd}${NAME_RELEASE}/${HW_MACHINE}/${HW_MACHINE_ARCH}/${NAME_BUILD}" + PLATFORM_OS="HardenedBSD" validate_release_url ;; -*-stable-build-latest|*-STABLE-BUILD-LATEST) +*-stable-build-latest|*-stable-BUILD-LATEST|*-STABLE-BUILD-LATEST) ## check for HardenedBSD(latest stable build release) - NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '([0-9]{1,2})(-stable-build-latest|-STABLE-BUILD-LATEST)$' | sed 's/STABLE/stable/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g') - NAME_RELEASE=$(echo ${NAME_VERIFY} | sed 's/-BUILD-LATEST//g') - NAME_BUILD=$(echo ${NAME_VERIFY} | sed 's/[0-9]\{1,2\}-stable-//g') + 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') + NAME_RELEASE=$(echo "${NAME_VERIFY}" | sed 's/-BUILD-LATEST//g') + NAME_BUILD=$(echo "${NAME_VERIFY}" | sed 's/[0-9]\{1,2\}-stable-//g') UPSTREAM_URL="${bastille_url_hardenedbsd}${NAME_RELEASE}/${HW_MACHINE}/${HW_MACHINE_ARCH}/${NAME_BUILD}" + PLATFORM_OS="HardenedBSD" validate_release_url ;; -current-build-[0-9]*|*-CURRENT-BUILD-[0-9]*) +current-build-[0-9]*|CURRENT-BUILD-[0-9]*) ## check for HardenedBSD(specific current build releases) - NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '(current-build|-CURRENT-BUILD)-([0-9]{1,3})' | sed 's/BUILD/build/g' | sed 's/CURRENT/current/g') - NAME_RELEASE=$(echo ${NAME_VERIFY} | sed 's/current-.*/current/g') - NAME_BUILD=$(echo ${NAME_VERIFY} | sed 's/current-//g') + NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '(current-build)-([0-9]{1,3})' | sed 's/BUILD/build/g' | sed 's/CURRENT/current/g') + NAME_RELEASE=$(echo "${NAME_VERIFY}" | sed 's/current-.*/current/g') + NAME_BUILD=$(echo "${NAME_VERIFY}" | sed 's/current-//g') UPSTREAM_URL="${bastille_url_hardenedbsd}${NAME_RELEASE}/${HW_MACHINE}/${HW_MACHINE_ARCH}/${NAME_BUILD}" + PLATFORM_OS="HardenedBSD" validate_release_url ;; -current-build-latest|*-CURRENT-BUILD-LATEST) +current-build-latest|current-BUILD-LATEST|CURRENT-BUILD-LATEST) ## check for HardenedBSD(latest current build release) - NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '(current-build-latest|-CURRENT-BUILD-LATEST)' | sed 's/CURRENT/current/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g') - NAME_RELEASE=$(echo ${NAME_VERIFY} | sed 's/current-.*/current/g') - NAME_BUILD=$(echo ${NAME_VERIFY} | sed 's/current-//g') + NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '(current-build-latest)' | sed 's/CURRENT/current/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g') + NAME_RELEASE=$(echo "${NAME_VERIFY}" | sed 's/current-.*/current/g') + NAME_BUILD=$(echo "${NAME_VERIFY}" | sed 's/current-//g') UPSTREAM_URL="${bastille_url_hardenedbsd}${NAME_RELEASE}/${HW_MACHINE}/${HW_MACHINE_ARCH}/${NAME_BUILD}" + PLATFORM_OS="HardenedBSD" validate_release_url ;; http?://github.com/*/*|http?://gitlab.com/*/*) diff --git a/usr/local/share/bastille/cmd.sh b/usr/local/share/bastille/cmd.sh index 2eb2bc42..f708acc7 100644 --- a/usr/local/share/bastille/cmd.sh +++ b/usr/local/share/bastille/cmd.sh @@ -53,11 +53,11 @@ if [ "${TARGET}" = 'ALL' ]; then JAILS=$(jls name) fi if [ "${TARGET}" != 'ALL' ]; then - JAILS=$(jls name | grep -w "${TARGET}") + JAILS=$(jls name | awk "/^${TARGET}$/") fi for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" - jexec -l ${_jail} $@ + jexec -l "${_jail}" "$@" echo done diff --git a/usr/local/share/bastille/console.sh b/usr/local/share/bastille/console.sh index e80f9f9c..897003f4 100644 --- a/usr/local/share/bastille/console.sh +++ b/usr/local/share/bastille/console.sh @@ -54,15 +54,15 @@ if [ "${TARGET}" = 'ALL' ]; then JAILS=$(jls name) fi if [ "${TARGET}" != 'ALL' ]; then - JAILS=$(jls name | grep -w "${TARGET}") + JAILS=$(jls name | awk "/^${TARGET}$/") fi validate_user() { - if jexec -l ${_jail} id "${USER}" >/dev/null 2>&1; then - USER_SHELL="$(jexec -l ${_jail} getent passwd "${USER}" | cut -d: -f7)" + if jexec -l "${_jail}" id "${USER}" >/dev/null 2>&1; then + USER_SHELL="$(jexec -l "${_jail}" getent passwd "${USER}" | cut -d: -f7)" if [ -n "${USER_SHELL}" ]; then - if jexec -l ${_jail} grep -qwF "${USER_SHELL}" /etc/shells; then - jexec -l ${_jail} /usr/bin/login -f "${USER}" + if jexec -l "${_jail}" grep -qwF "${USER_SHELL}" /etc/shells; then + jexec -l "${_jail}" /usr/bin/login -f "${USER}" else echo "Invalid shell for user ${USER}" fi @@ -76,10 +76,10 @@ validate_user() { for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" - if [ ! -z "${USER}" ]; then + if [ -n "${USER}" ]; then validate_user else - jexec -l ${_jail} /usr/bin/login -f root + jexec -l "${_jail}" /usr/bin/login -f root fi echo done diff --git a/usr/local/share/bastille/convert.sh b/usr/local/share/bastille/convert.sh index c6378836..3cb59beb 100644 --- a/usr/local/share/bastille/convert.sh +++ b/usr/local/share/bastille/convert.sh @@ -32,7 +32,7 @@ . /usr/local/etc/bastille/bastille.conf usage() { - echo -e "${COLOR_RED}Usage: bastille convert name.${COLOR_RESET}" + echo -e "${COLOR_RED}Usage: bastille convert TARGET.${COLOR_RESET}" exit 1 } @@ -63,7 +63,7 @@ convert_symlinks() { # Retrieve old symlinks temporarily for _link in ${SYMLINKS}; do if [ -L "${_link}" ]; then - mv ${_link} ${_link}.old + mv "${_link}" "${_link}.old" fi done @@ -73,7 +73,7 @@ convert_symlinks() { if [ -d "${bastille_releasesdir}/${RELEASE}/${_link}" ]; then cp -a "${bastille_releasesdir}/${RELEASE}/${_link}" "${bastille_jailsdir}/${TARGET}/root/${_link}" fi - if [ $? -ne 0 ]; then + if [ "$?" -ne 0 ]; then revert_convert fi fi @@ -82,11 +82,11 @@ convert_symlinks() { # Remove the old symlinks on success for _link in ${SYMLINKS}; do if [ -L "${_link}.old" ]; then - rm -r ${_link}.old + rm -r "${_link}.old" fi done else - error_notify "${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}" fi } @@ -103,7 +103,7 @@ revert_convert() { # Restore previous symlinks for _link in ${SYMLINKS}; do if [ -L "${_link}.old" ]; then - mv ${_link}.old ${_link} + mv "${_link}.old" "${_link}" fi done error_notify "${COLOR_GREEN}Changes for '${TARGET}' has been reverted.${COLOR_RESET}" @@ -115,8 +115,8 @@ start_convert() { echo -e "${COLOR_GREEN}Converting '${TARGET}' into a thickjail, this may take a while...${COLOR_RESET}" # Set some variables - RELEASE=$(grep -owE '([1-9]{2,2})\.[0-9](-RELEASE|-RC[1-2])' ${bastille_jailsdir}/${TARGET}/fstab) - FSTABMOD=$(grep -w "${bastille_releasesdir}/${RELEASE} ${bastille_jailsdir}/${TARGET}/root/.bastille" ${bastille_jailsdir}/${TARGET}/fstab) + RELEASE=$(grep -owE '([1-9]{2,2})\.[0-9](-RELEASE|-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") + FSTABMOD=$(grep -w "${bastille_releasesdir}/${RELEASE} ${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab") SYMLINKS="bin boot lib libexec rescue sbin usr/bin usr/include usr/lib usr/lib32 usr/libdata usr/libexec usr/ports usr/sbin usr/share usr/src" if [ -n "${RELEASE}" ]; then @@ -127,26 +127,21 @@ start_convert() { # Comment the line containing .bastille and rename mountpoint 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 + mv "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/root/.bastille.old" echo -e "${COLOR_GREEN}Conversion of '${TARGET}' completed successfully!${COLOR_RESET}" exit 0 else - error_notify "${COLOR_RED}Can't determine release version, See `bastille bootstrap`.${COLOR_RESET}" + error_notify "${COLOR_RED}Can't determine release version, See 'bastille bootstrap'.${COLOR_RESET}" fi - else - error_notify "${COLOR_RED}${TARGET} not found. See bootstrap.${COLOR_RESET}" + else + error_notify "${COLOR_RED}${TARGET} not found. See 'bastille create'.${COLOR_RESET}" fi } -# Check compatibility -if [ -n "$(freebsd-version | grep -i HBSD)" ]; then - error_notify "${COLOR_RED}Not yet supported on HardenedBSD.${COLOR_RESET}" -fi - # Check if container is running if [ -n "$(jls name | awk "/^${TARGET}$/")" ]; then - error_notify "${COLOR_RED}${TARGET} is running, See `bastille stop`.${COLOR_RESET}" + error_notify "${COLOR_RED}${TARGET} is running, See 'bastille stop'.${COLOR_RESET}" fi # Check if is a thin container diff --git a/usr/local/share/bastille/cp.sh b/usr/local/share/bastille/cp.sh index 088d5a7f..92681fba 100644 --- a/usr/local/share/bastille/cp.sh +++ b/usr/local/share/bastille/cp.sh @@ -55,7 +55,7 @@ if [ "${TARGET}" = 'ALL' ]; then JAILS=$(jls name) fi if [ "${TARGET}" != 'ALL' ]; then - JAILS=$(jls name | grep -w "${TARGET}") + JAILS=$(jls name | awk "/^${TARGET}$/") fi for _jail in ${JAILS}; do diff --git a/usr/local/share/bastille/create.sh b/usr/local/share/bastille/create.sh index 476931ec..6a19acf8 100644 --- a/usr/local/share/bastille/create.sh +++ b/usr/local/share/bastille/create.sh @@ -47,24 +47,34 @@ 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 - for quad in 1 2 3 4; do - if eval [ \$$quad -gt 255 ]; then - echo "fail ($ip)" - exit 1 - fi - done - if ifconfig | grep -w "$ip" >/dev/null; then - echo -e "${COLOR_YELLOW}Warning: ip address already in use ($ip).${COLOR_RESET}" - else - echo -e "${COLOR_GREEN}Valid: ($ip).${COLOR_RESET}" + IPX_ADDR="ip4.addr" + 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}" + IPX_ADDR="ip6.addr" + IP6_MODE="new" else - echo -e "${COLOR_RED}Invalid: ($ip).${COLOR_RESET}" - exit 1 + local IFS + if echo "${IP}" | grep -Eq '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))?$'; then + TEST_IP=$(echo "${IP}" | cut -d / -f1) + IFS=. + set ${TEST_IP} + for quad in 1 2 3 4; do + if eval [ \$$quad -gt 255 ]; then + echo "Invalid: (${TEST_IP})" + exit 1 + fi + done + if ifconfig | grep -qw "${TEST_IP}"; then + echo -e "${COLOR_YELLOW}Warning: ip address already in use (${TEST_IP}).${COLOR_RESET}" + else + echo -e "${COLOR_GREEN}Valid: (${IP}).${COLOR_RESET}" + fi + else + echo -e "${COLOR_RED}Invalid: (${IP}).${COLOR_RESET}" + exit 1 + fi fi } @@ -83,8 +93,8 @@ validate_netconf() { echo -e "${COLOR_RED}Invalid network configuration.${COLOR_RESET}" exit 1 fi - if [ ! -z "${bastille_jail_external}" ]; then - break + if [ -n "${bastille_jail_external}" ]; then + return 0 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}" @@ -108,6 +118,67 @@ validate_release() { fi } +generate_jail_conf() { + cat << EOF > "${bastille_jail_conf}" +${NAME} { + devfs_ruleset = 4; + enforce_statfs = 2; + exec.clean; + exec.consolelog = ${bastille_jail_log}; + exec.start = '/bin/sh /etc/rc'; + exec.stop = '/bin/sh /etc/rc.shutdown'; + host.hostname = ${NAME}; + mount.devfs; + mount.fstab = ${bastille_jail_fstab}; + path = ${bastille_jail_path}; + securelevel = 2; + + interface = ${bastille_jail_conf_interface}; + ${IPX_ADDR} = ${IP}; + ip6 = ${IP6_MODE}; +} +EOF +} + +generate_vnet_jail_conf() { + ## determine number of containers + 1 + ## iterate num and grep all jail configs + ## define uniq_epair + local list_jails_num=$(bastille list jails | wc -l | awk '{print $1}') + local num_range=$(expr "${list_jails_num}" + 1) + jail_list=$(bastille list jail) + for _num in $(seq 0 "${num_range}"); do + if [ -n "${jail_list}" ]; then + if ! grep -q "e0b_bastille${_num}" "${bastille_jailsdir}"/*/jail.conf; then + uniq_epair="bastille${_num}" + break + fi + fi + done + + ## generate config + cat << EOF > "${bastille_jail_conf}" +${NAME} { + devfs_ruleset = 13; + enforce_statfs = 2; + exec.clean; + exec.consolelog = ${bastille_jail_log}; + exec.start = '/bin/sh /etc/rc'; + exec.stop = '/bin/sh /etc/rc.shutdown'; + host.hostname = ${NAME}; + mount.devfs; + mount.fstab = ${bastille_jail_fstab}; + path = ${bastille_jail_path}; + securelevel = 2; + + vnet; + vnet.interface = e0b_${uniq_epair}; + exec.prestart += "jib addm ${uniq_epair} ${INTERFACE}"; + exec.poststop += "jib destroy ${uniq_epair}"; +} +EOF +} + create_jail() { bastille_jail_base="${bastille_jailsdir}/${NAME}/root/.bastille" ## dir bastille_jail_template="${bastille_jailsdir}/${NAME}/root/.template" ## dir @@ -120,11 +191,11 @@ create_jail() { if [ ! -d "${bastille_jailsdir}/${NAME}" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then - if [ ! -z "${bastille_zfs_zpool}" ]; then - ## create required zfs datasets - zfs create ${bastille_zfs_options} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME} + if [ -n "${bastille_zfs_zpool}" ]; then + ## create required zfs datasets, mountpoint inherited from system + zfs create ${bastille_zfs_options} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}" 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 + zfs create ${bastille_zfs_options} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME}/root" fi fi else @@ -150,43 +221,29 @@ create_jail() { 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} + echo -e "${bastille_releasesdir}/${RELEASE} ${bastille_jail_base} nullfs ro 0 0" > "${bastille_jail_fstab}" else - touch ${bastille_jail_fstab} + touch "${bastille_jail_fstab}" fi fi if [ ! -f "${bastille_jail_conf}" ]; then - if [ -z "${bastille_jail_loopback}" ] && [ ! -z "${bastille_jail_external}" ]; then + if [ -z "${bastille_jail_loopback}" ] && [ -n "${bastille_jail_external}" ]; then local bastille_jail_conf_interface=${bastille_jail_external} fi - if [ ! -z "${bastille_jail_loopback}" ] && [ -z "${bastille_jail_external}" ]; then + if [ -n "${bastille_jail_loopback}" ] && [ -z "${bastille_jail_external}" ]; then local bastille_jail_conf_interface=${bastille_jail_interface} fi - if [ ! -z ${INTERFACE} ]; then + if [ -n "${INTERFACE}" ]; then local bastille_jail_conf_interface=${INTERFACE} fi ## generate the jail configuration file - cat << EOF > ${bastille_jail_conf} -interface = ${bastille_jail_conf_interface}; -host.hostname = ${NAME}; -exec.consolelog = ${bastille_jail_log}; -path = ${bastille_jail_path}; -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 + if [ -n "${VNET_JAIL}" ]; then + generate_vnet_jail_conf + else + generate_jail_conf + fi fi ## using relative paths here @@ -195,7 +252,7 @@ EOF echo echo -e "${COLOR_GREEN}NAME: ${NAME}.${COLOR_RESET}" echo -e "${COLOR_GREEN}IP: ${IP}.${COLOR_RESET}" - if [ ! -z ${INTERFACE} ]; then + if [ -n "${INTERFACE}" ]; then echo -e "${COLOR_GREEN}INTERFACE: ${INTERFACE}.${COLOR_RESET}" fi echo -e "${COLOR_GREEN}RELEASE: ${RELEASE}.${COLOR_RESET}" @@ -217,10 +274,10 @@ EOF 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 + 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} + bastille destroy "${NAME}" exit 1 fi fi @@ -228,7 +285,7 @@ EOF 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 + if [ -n "${bastille_zfs_zpool}" ]; then ## perform release base replication ## sane bastille zfs options @@ -236,31 +293,32 @@ EOF ## 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} + 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 + 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} + 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 + 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} + 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 + 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} + bastille destroy "${NAME}" exit 1 fi fi @@ -272,19 +330,40 @@ EOF ## + cron_flags="-J 60" ## cedwards 20181118 if [ ! -f "${bastille_jail_rc_conf}" ]; then touch "${bastille_jail_rc_conf}" - /usr/sbin/sysrc -f "${bastille_jail_rc_conf}" syslogd_flags=-ss - /usr/sbin/sysrc -f "${bastille_jail_rc_conf}" sendmail_enable=NONE - /usr/sbin/sysrc -f "${bastille_jail_rc_conf}" cron_flags='-J 60' - echo + 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="DHCP" + else + /usr/sbin/sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="inet ${IP}" + 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} + cp -L "${bastille_resolv_conf}" "${bastille_jail_resolv_conf}" fi ## TZ: configurable (default: etc/UTC) - ln -s /usr/share/zoneinfo/${bastille_tzdata} etc/localtime + ln -s "/usr/share/zoneinfo/${bastille_tzdata}" etc/localtime } # Handle special-case commands first. @@ -294,44 +373,50 @@ help|-h|--help) ;; esac -if [ $(echo $3 | grep '@' ) ]; then - BASTILLE_JAIL_IP=$(echo $3 | awk -F@ '{print $2}') - BASTILLE_JAIL_INTERFACES=$( echo $3 | awk -F@ '{print $1}') +if echo "$3" | grep '@'; then + BASTILLE_JAIL_IP=$(echo "$3" | awk -F@ '{print $2}') + BASTILLE_JAIL_INTERFACES=$( echo "$3" | awk -F@ '{print $1}') fi -TYPE="$1" -NAME="$2" -RELEASE="$3" -IP="$4" -INTERFACE="$5" +## reset this options +THICK_JAIL="" +VNET_JAIL="" -## 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}" +## handle combined options then shift +if [ "${1}" = "-T" -o "${1}" = "--thick" -o "${1}" = "thick" ] && \ + [ "${2}" = "-V" -o "${2}" = "--vnet" -o "${2}" = "vnet" ]; then + THICK_JAIL="1" + VNET_JAIL="1" + shift 2 +else + ## handle single options + case "${1}" in + -T|--thick|thick) + shift + THICK_JAIL="1" + ;; + -V|--vnet|vnet) + shift + VNET_JAIL="1" + ;; + -*) + echo -e "${COLOR_RED}Unknown Option.${COLOR_RESET}" + usage + ;; + esac +fi + +NAME="$1" +RELEASE="$2" +IP="$3" +INTERFACE="$4" + +if [ $# -gt 4 ] || [ $# -lt 3 ]; then usage - ;; -*) - if [ $# -gt 4 ] || [ $# -lt 3 ]; then - usage - fi - THICK_JAIL="" - NAME="$1" - RELEASE="$2" - IP="$3" - INTERFACE="$4" - ;; -esac +fi ## don't allow for dots(.) in container names -if [ $(echo "${NAME}" | grep "[.]") ]; then +if echo "${NAME}" | grep -q "[.]"; then echo -e "${COLOR_RED}Container names may not contain a dot(.)!${COLOR_RESET}" exit 1 fi @@ -345,27 +430,27 @@ case "${RELEASE}" in ;; *-stable-LAST|*-STABLE-last|*-stable-last|*-STABLE-LAST) ## check for HardenedBSD releases name(previous infrastructure) - 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') + 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) - NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '([0-9]{1,2})(-stable-build|-STABLE-BUILD)-([0-9]{1,3})$' | sed 's/BUILD/build/g' | sed 's/STABLE/stable/g') + 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|*-stable-BUILD-LATEST|*-STABLE-BUILD-LATEST) ## check for HardenedBSD(latest stable build release) - NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '([0-9]{1,2})(-stable-build-latest|-STABLE-BUILD-LATEST)$' | sed 's/STABLE/stable/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g') + 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) - NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '(current-build|-CURRENT-BUILD)-([0-9]{1,3})' | sed 's/BUILD/build/g' | sed 's/CURRENT/current/g') + 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|current-BUILD-LATEST|CURRENT-BUILD-LATEST) ## check for HardenedBSD(latest current build release) - NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '(current-build-latest|-CURRENT-BUILD-LATEST)' | sed 's/CURRENT/current/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g') + 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 ;; *) @@ -382,7 +467,7 @@ fi ## check for required release if [ ! -d "${bastille_releasesdir}/${RELEASE}" ]; then - echo -e "${COLOR_RED}Release must be bootstrapped first; see `bastille bootstrap`.${COLOR_RESET}" + echo -e "${COLOR_RED}Release must be bootstrapped first; see 'bastille bootstrap'.${COLOR_RESET}" exit 1 fi @@ -392,17 +477,17 @@ if [ -n "${NAME}" ]; then fi ## check if ip address is valid -if [ ! -z "${IP}" ]; then +if [ -n "${IP}" ]; then validate_ip else usage fi ## check if interface is valid -if [ ! -z ${INTERFACE} ]; then +if [ -n "${INTERFACE}" ]; then validate_netif else validate_netconf fi -create_jail ${NAME} ${RELEASE} ${IP} ${INTERFACE} +create_jail "${NAME}" "${RELEASE}" "${IP}" "${INTERFACE}" diff --git a/usr/local/share/bastille/destroy.sh b/usr/local/share/bastille/destroy.sh index b9b07091..c0c1fdd7 100644 --- a/usr/local/share/bastille/destroy.sh +++ b/usr/local/share/bastille/destroy.sh @@ -42,7 +42,7 @@ destroy_jail() { if [ "$(jls name | awk "/^${TARGET}$/")" ]; then if [ "${FORCE}" = "1" ]; then - bastille stop ${TARGET} + bastille stop "${TARGET}" else echo -e "${COLOR_RED}Jail running.${COLOR_RESET}" echo -e "${COLOR_RED}See 'bastille stop ${TARGET}'.${COLOR_RESET}" @@ -58,25 +58,25 @@ destroy_jail() { if [ -d "${bastille_jail_base}" ]; then echo -e "${COLOR_GREEN}Deleting Jail: ${TARGET}.${COLOR_RESET}" if [ "${bastille_zfs_enable}" = "YES" ]; then - if [ ! -z "${bastille_zfs_zpool}" ]; then - if [ ! -z "${TARGET}" ]; then + if [ -n "${bastille_zfs_zpool}" ]; then + if [ -n "${TARGET}" ]; then ## remove jail zfs dataset recursively - zfs destroy -r ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET} + zfs destroy -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}" fi fi fi if [ -d "${bastille_jail_base}" ]; then ## removing all flags - chflags -R noschg ${bastille_jail_base} + chflags -R noschg "${bastille_jail_base}" ## remove jail base - rm -rf ${bastille_jail_base} + rm -rf "${bastille_jail_base}" fi ## archive jail log if [ -f "${bastille_jail_log}" ]; then - mv ${bastille_jail_log} ${bastille_jail_log}-$(date +%F) + 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}" fi @@ -88,7 +88,6 @@ destroy_rel() { ## check release name match before destroy if [ -n "${NAME_VERIFY}" ]; then TARGET="${NAME_VERIFY}" - break else usage fi @@ -100,7 +99,7 @@ destroy_rel() { if [ -d "${bastille_jailsdir}" ]; then JAIL_LIST=$(ls "${bastille_jailsdir}" | sed "s/\n//g") for _jail in ${JAIL_LIST}; do - if grep -qwo "${TARGET}" ${bastille_jailsdir}/${_jail}/fstab 2>/dev/null; then + if grep -qwo "${TARGET}" "${bastille_jailsdir}/${_jail}/fstab" 2>/dev/null; then echo -e "${COLOR_RED}Notice: (${_jail}) depends on ${TARGET} base.${COLOR_RESET}" BASE_HASCHILD="1" fi @@ -114,11 +113,11 @@ destroy_rel() { if [ "${BASE_HASCHILD}" -eq "0" ]; then echo -e "${COLOR_GREEN}Deleting base: ${TARGET}.${COLOR_RESET}" if [ "${bastille_zfs_enable}" = "YES" ]; then - if [ ! -z "${bastille_zfs_zpool}" ]; then - zfs destroy ${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${TARGET} + if [ -n "${bastille_zfs_zpool}" ]; then + zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${TARGET}" if [ "${FORCE}" = "1" ]; then if [ -d "${bastille_cachedir}/${TARGET}" ]; then - zfs destroy ${bastille_zfs_zpool}/${bastille_zfs_prefix}/cache/${TARGET} + zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/cache/${TARGET}" fi fi fi @@ -126,10 +125,10 @@ destroy_rel() { if [ -d "${bastille_rel_base}" ]; then ## removing all flags - chflags -R noschg ${bastille_rel_base} + chflags -R noschg "${bastille_rel_base}" ## remove jail base - rm -rf ${bastille_rel_base} + rm -rf "${bastille_rel_base}" fi if [ "${FORCE}" = "1" ]; then @@ -152,29 +151,27 @@ help|-h|--help) ;; esac -OPTION="${1}" -TARGET="${2}" +## reset this options +FORCE="" ## handle additional options -case "${OPTION}" in --f|--force) - if [ $# -gt 2 ] || [ $# -lt 2 ]; then +case "${1}" in + -f|--force|force) + FORCE="1" + shift + ;; + -*) + echo -e "${COLOR_RED}Unknown Option.${COLOR_RESET}" usage - fi - FORCE="1" - ;; --*) - echo -e "${COLOR_RED}Unknown Option.${COLOR_RESET}" - usage - ;; -*) - if [ $# -gt 1 ] || [ $# -lt 1 ]; then - usage - fi - TARGET="${1}" - ;; + ;; esac +TARGET="${1}" + +if [ $# -gt 1 ] || [ $# -lt 1 ]; then + usage +fi + ## check what should we clean case "${TARGET}" in *-RELEASE|*-release|*-RC1|*-rc1|*-RC2|*-rc2) @@ -184,27 +181,27 @@ case "${TARGET}" in ;; *-stable-LAST|*-STABLE-last|*-stable-last|*-STABLE-LAST) ## check for HardenedBSD releases name - NAME_VERIFY=$(echo "${TARGET}" | grep -iwE '^([1-9]{2,2})(-stable-LAST|-STABLE-last|-stable-last|-STABLE-LAST)$' | sed 's/STABLE/stable/g' | sed 's/last/LAST/g') + NAME_VERIFY=$(echo "${TARGET}" | grep -iwE '^([1-9]{2,2})(-stable-last)$' | sed 's/STABLE/stable/g' | sed 's/last/LAST/g') destroy_rel ;; *-stable-build-[0-9]*|*-STABLE-BUILD-[0-9]*) ## check for HardenedBSD(specific stable build releases) - NAME_VERIFY=$(echo "${TARGET}" | grep -iwE '([0-9]{1,2})(-stable-build|-STABLE-BUILD)-([0-9]{1,3})$' | sed 's/BUILD/build/g' | sed 's/STABLE/stable/g') + NAME_VERIFY=$(echo "${TARGET}" | grep -iwE '([0-9]{1,2})(-stable-build)-([0-9]{1,3})$' | sed 's/BUILD/build/g' | sed 's/STABLE/stable/g') destroy_rel ;; -*-stable-build-latest|*-STABLE-BUILD-LATEST) +*-stable-build-latest|*-stable-BUILD-LATEST|*-STABLE-BUILD-LATEST) ## check for HardenedBSD(latest stable build release) - NAME_VERIFY=$(echo "${TARGET}" | grep -iwE '([0-9]{1,2})(-stable-build-latest|-STABLE-BUILD-LATEST)$' | sed 's/STABLE/stable/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g') + NAME_VERIFY=$(echo "${TARGET}" | grep -iwE '([0-9]{1,2})(-stable-build-latest)$' | sed 's/STABLE/stable/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g') destroy_rel ;; current-build-[0-9]*|CURRENT-BUILD-[0-9]*) ## check for HardenedBSD(specific current build releases) - NAME_VERIFY=$(echo "${TARGET}" | grep -iwE '(current-build|-CURRENT-BUILD)-([0-9]{1,3})' | sed 's/BUILD/build/g' | sed 's/CURRENT/current/g') + NAME_VERIFY=$(echo "${TARGET}" | grep -iwE '(current-build)-([0-9]{1,3})' | sed 's/BUILD/build/g' | sed 's/CURRENT/current/g') destroy_rel ;; -current-build-latest|CURRENT-BUILD-LATEST) +current-build-latest|current-BUILD-LATEST|CURRENT-BUILD-LATEST) ## check for HardenedBSD(latest current build release) - NAME_VERIFY=$(echo "${TARGET}" | grep -iwE '(current-build-latest|-CURRENT-BUILD-LATEST)$' | sed 's/CURRENT/current/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g') + NAME_VERIFY=$(echo "${TARGET}" | grep -iwE '(current-build-latest)$' | sed 's/CURRENT/current/g' | sed 's/build/BUILD/g' | sed 's/latest/LATEST/g') destroy_rel ;; *) diff --git a/usr/local/share/bastille/edit.sh b/usr/local/share/bastille/edit.sh new file mode 100644 index 00000000..8f741b10 --- /dev/null +++ b/usr/local/share/bastille/edit.sh @@ -0,0 +1,72 @@ +#!/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/colors.pre.sh +. /usr/local/etc/bastille/bastille.conf + +usage() { + echo -e "${COLOR_RED}Usage: bastille edit TARGET [filename]${COLOR_RESET}" + exit 1 +} + +# Handle special-case commands first. +case "$1" in +help|-h|--help) + usage + ;; +esac + +if [ $# -gt 2 ] || [ $# -lt 1 ]; then + usage +fi + +TARGET="${1}" +if [ $# == 2 ]; then + TARGET_FILENAME="${2}" +fi + +if [ -z "${EDITOR}" ]; then + EDITOR=vi +fi + +if [ "${TARGET}" = 'ALL' ]; then + JAILS=$(bastille list jails) +fi +if [ "${TARGET}" != 'ALL' ]; then + JAILS=$(bastille list jails | awk "/^${TARGET}$/") +fi + +for _jail in ${JAILS}; do + if [ -n "${TARGET_FILENAME}" ]; then + "${EDITOR}" "${bastille_jailsdir}/${_jail}/${TARGET_FILENAME}" + else + "${EDITOR}" "${bastille_jailsdir}/${_jail}/jail.conf" + fi +done diff --git a/usr/local/share/bastille/export.sh b/usr/local/share/bastille/export.sh index 5b902489..b2b5068f 100644 --- a/usr/local/share/bastille/export.sh +++ b/usr/local/share/bastille/export.sh @@ -63,32 +63,32 @@ jail_export() DATE=$(date +%F-%H%M%S) if [ -d "${bastille_jailsdir}/${TARGET}" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then - if [ ! -z "${bastille_zfs_zpool}" ]; 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}" # Take a recursive temporary snapshot SNAP_NAME="bastille_export-${DATE}" - zfs snapshot -r ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@${SNAP_NAME} + zfs snapshot -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}"@"${SNAP_NAME}" # Export the container recursively and cleanup temporary snapshots - zfs send -R ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@${SNAP_NAME} | \ - xz ${bastille_compress_xz_options} > ${bastille_backupsdir}/${TARGET}_${DATE}.${FILE_EXT} - zfs destroy -r ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@${SNAP_NAME} + zfs send -R "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}"@"${SNAP_NAME}" | \ + xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}.${FILE_EXT}" + zfs destroy -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}"@"${SNAP_NAME}" fi else # Create standard backup archive FILE_EXT="txz" echo -e "${COLOR_GREEN}Exporting '${TARGET}' to a compressed .${FILE_EXT} archive...${COLOR_RESET}" - cd ${bastille_jailsdir} && tar -cf - ${TARGET} | xz ${bastille_compress_xz_options} > ${bastille_backupsdir}/${TARGET}_${DATE}.${FILE_EXT} + cd "${bastille_jailsdir}" && tar -cf - "${TARGET}" | xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}.${FILE_EXT}" fi - if [ $? -ne 0 ]; then + if [ "$?" -ne 0 ]; then error_notify "${COLOR_RED}Failed to export '${TARGET}' container.${COLOR_RESET}" else # Generate container checksum file - cd ${bastille_backupsdir} - sha256 -q ${TARGET}_${DATE}.${FILE_EXT} > ${TARGET}_${DATE}.sha256 + 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}" exit 0 fi diff --git a/usr/local/share/bastille/htop.sh b/usr/local/share/bastille/htop.sh index a675f38b..0af8f2d5 100644 --- a/usr/local/share/bastille/htop.sh +++ b/usr/local/share/bastille/htop.sh @@ -54,7 +54,7 @@ if [ "${TARGET}" = 'ALL' ]; then JAILS=$(jls name) fi if [ "${TARGET}" != 'ALL' ]; then - JAILS=$(jls name | grep -w "${TARGET}") + JAILS=$(jls name | awk "/^${TARGET}$/") fi for _jail in ${JAILS}; do diff --git a/usr/local/share/bastille/import.sh b/usr/local/share/bastille/import.sh index 238c8dca..53c8057f 100644 --- a/usr/local/share/bastille/import.sh +++ b/usr/local/share/bastille/import.sh @@ -60,8 +60,8 @@ validate_archive() { # Compare checksums on the target archive if [ -f "${bastille_backupsdir}/${TARGET}" ]; then echo -e "${COLOR_GREEN}Validating file: ${TARGET}...${COLOR_RESET}" - SHA256_DIST=$(cat ${bastille_backupsdir}/${FILE_TRIM}.sha256) - SHA256_FILE=$(sha256 -q ${bastille_backupsdir}/${TARGET}) + SHA256_DIST=$(cat "${bastille_backupsdir}/${FILE_TRIM}.sha256") + SHA256_FILE=$(sha256 -q "${bastille_backupsdir}/${TARGET}") if [ "${SHA256_FILE}" != "${SHA256_DIST}" ]; then error_notify "${COLOR_RED}Failed validation for ${TARGET}.${COLOR_RESET}" else @@ -72,11 +72,19 @@ validate_archive() { update_zfsmount() { # 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}') + 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}" - zfs set mountpoint=${bastille_jailsdir}/${TARGET_TRIM}/root ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root + zfs set mountpoint="${bastille_jailsdir}/${TARGET_TRIM}/root" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" + fi + + # Mount new container ZFS datasets + if ! zfs mount | grep "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}"; then + zfs mount "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" + fi + if ! zfs mount | grep "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root"; then + zfs mount "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" fi } @@ -84,11 +92,11 @@ update_jailconf() { # Update jail.conf paths 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 + if ! grep -qw "path = ${bastille_jailsdir}/${TARGET_TRIM}/root;" "${JAIL_CONFIG}"; then 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|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|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}" fi fi } @@ -97,67 +105,154 @@ update_fstab() { # Update fstab .bastille mountpoint on thin containers only # Set some variables FSTAB_CONFIG="${bastille_jailsdir}/${TARGET_TRIM}/fstab" - FSTAB_RELEASE=$(grep -owE '([1-9]{2,2})\.[0-9](-RELEASE|-RC[1-2]|-stable-build-[0-9]{1,3})' ${FSTAB_CONFIG}) - FSTAB_CURRENT=$(grep -w ".*/releases/.*/jails/${TARGET_TRIM}/root/.bastille" ${FSTAB_CONFIG}) + FSTAB_RELEASE=$(grep -owE '([1-9]{2,2})\.[0-9](-RELEASE|-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)' "${FSTAB_CONFIG}") + FSTAB_CURRENT=$(grep -w ".*/releases/.*/jails/${TARGET_TRIM}/root/.bastille" "${FSTAB_CONFIG}") FSTAB_NEWCONF="${bastille_releasesdir}/${FSTAB_RELEASE} ${bastille_jailsdir}/${TARGET_TRIM}/root/.bastille nullfs ro 0 0" 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 + if ! grep -qw "${bastille_releasesdir}/${FSTAB_RELEASE}.*${bastille_jailsdir}/${TARGET_TRIM}/root/.bastille" "${FSTAB_CONFIG}"; then echo -e "${COLOR_GREEN}Updating fstab...${COLOR_RESET}" - sed -i '' "s|${FSTAB_CURRENT}|${FSTAB_NEWCONF}|" ${FSTAB_CONFIG} + sed -i '' "s|${FSTAB_CURRENT}|${FSTAB_NEWCONF}|" "${FSTAB_CONFIG}" fi fi } +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 + JSON_CONFIG="${bastille_jailsdir}/${TARGET_TRIM}/config.json.old" + IPV4_CONFIG=$(grep -wo '\"ip4_addr\": \".*\"' "${JSON_CONFIG}" | tr -d '" ' | sed 's/ip4_addr://;s/.\{1\}$//') + IPV6_CONFIG=$(grep -wo '\"ip6_addr\": \".*\"' "${JSON_CONFIG}" | tr -d '" ' | sed 's/ip6_addr://;s/.\{1\}$//') + + if [ -n "${IPV4_CONFIG}" ]; then + NETIF_CONFIG=$(echo "${IPV4_CONFIG}" | sed 's/|.*//g') + IPX_ADDR="ip4.addr" + IP_CONFIG="${IPV4_CONFIG}" + IP6_MODE="disable" + elif [ -n "${IPV6_CONFIG}" ]; then + NETIF_CONFIG=$(echo "${IPV6_CONFIG}" | sed 's/|.*//g') + IPX_ADDR="ip6.addr" + IP_CONFIG="${IPV6_CONFIG}" + IP6_MODE="new" + fi + + # Let the user configure it manually + if [ -z "${NETIF_CONFIG}" ]; then + NETIF_CONFIG="lo1" + IPX_ADDR="ip4.addr" + IP_CONFIG="-" + IP6_MODE="disable" + echo -e "${COLOR_YELLOW}Warning: See 'bastille edit ${TARGET_TRIM} jail.conf' for manual configuration${COLOR_RESET}" + fi + + # Generate new empty fstab file + touch "${bastille_jailsdir}/${TARGET_TRIM}/fstab" + + # Generate a basic jail configuration file on foreign imports + cat << EOF > "${bastille_jailsdir}/${TARGET_TRIM}/jail.conf" +${TARGET_TRIM} { + devfs_ruleset = 4; + enforce_statfs = 2; + exec.clean; + exec.consolelog = ${bastille_logsdir}/${TARGET_TRIM}_console.log; + exec.start = '/bin/sh /etc/rc'; + exec.stop = '/bin/sh /etc/rc.shutdown'; + host.hostname = ${TARGET_TRIM}; + mount.devfs; + mount.fstab = ${bastille_jailsdir}/${TARGET_TRIM}/fstab; + path = ${bastille_jailsdir}/${TARGET_TRIM}/root; + securelevel = 2; + + interface = ${NETIF_CONFIG}; + ${IPX_ADDR} = ${IP_CONFIG}; + ip6 = ${IP6_MODE}; +} +EOF +} + jail_import() { # Attempt to import container from file - FILE_TRIM=$(echo ${TARGET} | sed 's/.[txz]\{2,3\}//') - FILE_EXT=$(echo ${TARGET} | cut -d '.' -f2) + FILE_TRIM=$(echo "${TARGET}" | sed 's/.[txz]\{2,3\}//g;s/.zip//g') + FILE_EXT=$(echo "${TARGET}" | cut -d '.' -f2) validate_archive if [ -d "${bastille_jailsdir}" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then - if [ ! -z "${bastille_zfs_zpool}" ]; then + 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}" - xz ${bastille_decompress_xz_options} ${bastille_backupsdir}/${TARGET} | \ - zfs receive -u ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM} + xz ${bastille_decompress_xz_options} "${bastille_backupsdir}/${TARGET}" | \ + zfs receive -u "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" # Update ZFS mountpoint property if required # This is required on foreign imports only update_zfsmount - # Mount new container ZFS datasets - zfs mount ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM} - zfs mount ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root elif [ "${FILE_EXT}" = "txz" ]; then # Prepare the ZFS environment and restore from existing tar.xz file echo -e "${COLOR_GREEN}Importing '${TARGET_TRIM}' form .${FILE_EXT} archive.${COLOR_RESET}" echo -e "${COLOR_GREEN}Preparing zfs environment...${COLOR_RESET}" - zfs create ${bastille_zfs_options} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM} - zfs create ${bastille_zfs_options} -o mountpoint=${bastille_jailsdir}/${TARGET_TRIM}/root \ - ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root + zfs create ${bastille_zfs_options} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" + zfs create ${bastille_zfs_options} -o mountpoint="${bastille_jailsdir}/${TARGET_TRIM}/root" \ + "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" # Extract required files to the new datasets echo -e "${COLOR_GREEN}Extracting files from '${TARGET}' archive...${COLOR_RESET}" - 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 - zfs destroy -r ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM} + 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 + zfs destroy -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" error_notify "${COLOR_RED}Failed to extract files from '${TARGET}' archive.${COLOR_RESET}" fi + elif [ "${FILE_EXT}" = "zip" ]; then + # Attempt to import a foreign container + echo -e "${COLOR_GREEN}Importing '${TARGET_TRIM}' from foreign compressed .${FILE_EXT} archive.${COLOR_RESET}" + # Sane bastille zfs options + ZFS_OPTIONS=$(echo ${bastille_zfs_options} | sed 's/-o//g') + + # Extract required files from the zip archive + cd "${bastille_backupsdir}" && unzip -j "${TARGET}" + if [ "$?" -ne 0 ]; then + error_notify "${COLOR_RED}Failed to extract files from '${TARGET}' archive.${COLOR_RESET}" + rm -f "${FILE_TRIM}" "${FILE_TRIM}_root" + fi + echo -e "${COLOR_GREEN}Receiving zfs data stream...${COLOR_RESET}" + 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 "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" < "${FILE_TRIM}_root" + + # Update ZFS mountpoint property if required + update_zfsmount + + # Keep old configuration files for user reference + if [ -f "${bastille_jailsdir}/${TARGET_TRIM}/config.json" ]; then + mv "${bastille_jailsdir}/${TARGET_TRIM}/config.json" "${bastille_jailsdir}/${TARGET_TRIM}/config.json.old" + fi + if [ -f "${bastille_jailsdir}/${TARGET_TRIM}/fstab" ]; then + mv "${bastille_jailsdir}/${TARGET_TRIM}/fstab" "${bastille_jailsdir}/${TARGET_TRIM}/fstab.old" + fi + + # Cleanup unwanted files + rm -f "${FILE_TRIM}" "${FILE_TRIM}_root" + + # Generate fstab and jail.conf files + generate_config else error_notify "${COLOR_RED}Unknown archive format.${COLOR_RESET}" fi fi else # Import from standard tar.xz archive on UFS systems - echo -e "${COLOR_GREEN}Extracting files from '${TARGET}' archive...${COLOR_RESET}" - tar -Jxf ${bastille_backupsdir}/${TARGET} -C ${bastille_jailsdir} + if [ "${FILE_EXT}" = "txz" ]; then + echo -e "${COLOR_GREEN}Extracting files from '${TARGET}' archive...${COLOR_RESET}" + tar -Jxf "${bastille_backupsdir}/${TARGET}" -C "${bastille_jailsdir}" + else + error_notify "${COLOR_RED}Unsupported archive format.${COLOR_RESET}" + fi fi - if [ $? -ne 0 ]; then + if [ "$?" -ne 0 ]; then error_notify "${COLOR_RED}Failed to import from '${TARGET}' archive.${COLOR_RESET}" else # Update the jail.conf and fstab if required diff --git a/usr/local/share/bastille/limits.sh b/usr/local/share/bastille/limits.sh index d1bbd692..483a0341 100644 --- a/usr/local/share/bastille/limits.sh +++ b/usr/local/share/bastille/limits.sh @@ -63,12 +63,12 @@ if [ "${TARGET}" = 'ALL' ]; then fi if [ "${TARGET}" != 'ALL' ]; then - JAILS=$(jls name | grep -w "${TARGET}") + JAILS=$(jls name | awk "/^${TARGET}$/") fi for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" echo -e "${TYPE} ${VALUE}" - rctl -a jail:${_jail}:${OPTION}:deny=${VALUE}/jail + rctl -a jail:"${_jail}":"${OPTION}":deny="${VALUE}/jail" echo -e "${COLOR_RESET}" done diff --git a/usr/local/share/bastille/pkg.sh b/usr/local/share/bastille/pkg.sh index 081ee3ff..4651cbec 100644 --- a/usr/local/share/bastille/pkg.sh +++ b/usr/local/share/bastille/pkg.sh @@ -53,11 +53,11 @@ if [ "${TARGET}" = 'ALL' ]; then JAILS=$(jls name) fi if [ "${TARGET}" != 'ALL' ]; then - JAILS=$(jls name | grep -w "${TARGET}") + JAILS=$(jls name | awk "/^${TARGET}$/") fi for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" - jexec -l ${_jail} /usr/sbin/pkg $@ + jexec -l "${_jail}" /usr/sbin/pkg "$@" echo done diff --git a/usr/local/share/bastille/rdr.sh b/usr/local/share/bastille/rdr.sh index bca00a6d..9c4ebfed 100644 --- a/usr/local/share/bastille/rdr.sh +++ b/usr/local/share/bastille/rdr.sh @@ -68,7 +68,7 @@ if [ -z "${JAIL_IP}" -o "${JAIL_IP}" = "-" ]; then fi # Check rdr-anchor is setup in pf.conf -if !(pfctl -sn | grep rdr-anchor | grep 'rdr/\*' >/dev/null); then +if ! (pfctl -sn | grep rdr-anchor | grep 'rdr/\*' >/dev/null); then echo -e "${COLOR_RED}rdr-anchor not found in pf.conf${COLOR_RESET}" exit 1 fi @@ -113,6 +113,3 @@ while [ $# -gt 0 ]; do ;; esac done - - - diff --git a/usr/local/share/bastille/rename.sh b/usr/local/share/bastille/rename.sh new file mode 100644 index 00000000..29fb5c52 --- /dev/null +++ b/usr/local/share/bastille/rename.sh @@ -0,0 +1,128 @@ +#!/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/colors.pre.sh +. /usr/local/etc/bastille/bastille.conf + +usage() { + echo -e "${COLOR_RED}Usage: bastille rename [TARGET] [NEW_NAME].${COLOR_RESET}" + exit 1 +} + +error_notify() { + # Notify message on error and exit + echo -e "$*" >&2 + exit 1 +} + +# Handle special-case commands first +case "$1" in +help|-h|--help) + usage + ;; +esac + +if [ $# -gt 2 ] || [ $# -lt 2 ]; then + usage +fi + +TARGET="${1}" +NEWNAME="${2}" +shift + +update_jailconf() { + # Update jail.conf + JAIL_CONFIG="${bastille_jailsdir}/${NEWNAME}/jail.conf" + if [ -f "${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|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|mount.fstab = .*;|mount.fstab = ${bastille_jailsdir}/${NEWNAME}/fstab;|" "${JAIL_CONFIG}" + sed -i '' "s|${TARGET} {|${NEWNAME} {|" "${JAIL_CONFIG}" + fi + fi +} + +update_fstab() { + # Update fstab to use the new name + FSTAB_CONFIG="${bastille_jailsdir}/${NEWNAME}/fstab" + if [ -f "${FSTAB_CONFIG}" ]; then + FSTAB_RELEASE=$(grep -owE '([1-9]{2,2})\.[0-9](-RELEASE|-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)' "${FSTAB_CONFIG}") + FSTAB_CURRENT=$(grep -w ".*/releases/.*/jails/${TARGET}/root/.bastille" "${FSTAB_CONFIG}") + FSTAB_NEWCONF="${bastille_releasesdir}/${FSTAB_RELEASE} ${bastille_jailsdir}/${NEWNAME}/root/.bastille nullfs ro 0 0" + if [ -n "${FSTAB_CURRENT}" ] && [ -n "${FSTAB_NEWCONF}" ]; then + # If both variables are set, update as needed + if ! grep -qw "${bastille_releasesdir}/${FSTAB_RELEASE}.*${bastille_jailsdir}/${NEWNAME}/root/.bastille" "${FSTAB_CONFIG}"; then + sed -i '' "s|${FSTAB_CURRENT}|${FSTAB_NEWCONF}|" "${FSTAB_CONFIG}" + fi + fi + fi +} + +change_name() { + # Attempt container name change + if [ -d "${bastille_jailsdir}/${TARGET}" ]; then + echo -e "${COLOR_GREEN}Attempting to rename '${TARGET}' to ${NEWNAME}...${COLOR_RESET}" + if [ "${bastille_zfs_enable}" = "YES" ]; then + if [ -n "${bastille_zfs_zpool}" ]; then + # Rename ZFS dataset and mount points accordingly + zfs rename "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NEWNAME}" + zfs set mountpoint="${bastille_jailsdir}/${NEWNAME}/root" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NEWNAME}/root" + fi + else + # Just rename the jail directory + mv "${bastille_jailsdir}/${TARGET}" "${bastille_jailsdir}/${NEWNAME}" + fi + else + error_notify "${COLOR_RED}${TARGET} not found. See bootstrap.${COLOR_RESET}" + fi + + # Update jail configuration files accordingly + update_jailconf + update_fstab + + # Remove the old jail directory if exist + if [ -d "${bastille_jailsdir}/${TARGET}" ]; then + rm -r "${bastille_jailsdir}/${TARGET}" + fi + if [ "$?" -ne 0 ]; then + error_notify "${COLOR_RED}An error has occurred while attempting to rename '${TARGET}'.${COLOR_RESET}" + else + echo -e "${COLOR_GREEN}Renamed '${TARGET}' to '${NEWNAME}' successfully.${COLOR_RESET}" + fi +} + +# Check if container is running +if [ -n "$(jls name | awk "/^${TARGET}$/")" ]; then + error_notify "${COLOR_RED}${TARGET} is running, See 'bastille stop'.${COLOR_RESET}" +fi + +change_name diff --git a/usr/local/share/bastille/service.sh b/usr/local/share/bastille/service.sh index 17c6578d..4a20ac58 100644 --- a/usr/local/share/bastille/service.sh +++ b/usr/local/share/bastille/service.sh @@ -54,11 +54,11 @@ if [ "${TARGET}" = 'ALL' ]; then fi if [ "${TARGET}" != 'ALL' ]; then - JAILS=$(jls name | grep -w "${TARGET}") + JAILS=$(jls name | awk "/^${TARGET}$/") fi for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" - jexec -l ${_jail} /usr/sbin/service $@ + 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 c16e6cae..9aa33684 100644 --- a/usr/local/share/bastille/start.sh +++ b/usr/local/share/bastille/start.sh @@ -55,6 +55,10 @@ if [ "${TARGET}" = 'ALL' ]; then fi if [ "${TARGET}" != 'ALL' ]; then JAILS=$(bastille list jails | awk "/^${TARGET}$/") + ## check if exist + if [ ! -d "${bastille_jailsdir}/${TARGET}" ]; then + echo -e "${COLOR_RED}[${TARGET}]: Not found.${COLOR_RESET}" + fi fi for _jail in ${JAILS}; do @@ -64,13 +68,19 @@ for _jail in ${JAILS}; do ## test if not running elif [ ! "$(jls name | awk "/^${_jail}$/")" ]; then - echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" - jail -f "${bastille_jailsdir}/${_jail}/jail.conf" -c ${_jail} + ## 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 ifconfig | grep -w "$ip" >/dev/null; then - echo -e "${COLOR_RED}Error: IP address ($ip) already in use.${COLOR_RESET}" - exit 1 + if [ -n "${ip}" ]; then + if ifconfig | grep -w "${ip}" >/dev/null; then + echo -e "${COLOR_RED}Error: IP address (${ip}) already in use.${COLOR_RESET}" + exit 1 + fi fi + + ## start the container + echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" + jail -f "${bastille_jailsdir}/${_jail}/jail.conf" -c "${_jail}" + ## add rctl limits if [ -s "${bastille_jailsdir}/${_jail}/rctl.conf" ]; then while read _limits; do @@ -80,7 +90,7 @@ for _jail in ${JAILS}; do ## add ip4.addr to firewall table:jails if [ ! -z "${bastille_jail_loopback}" ]; then - pfctl -q -t jails -T add $(jls -j ${_jail} ip4.addr) + pfctl -q -t jails -T add "$(jls -j "${_jail}" ip4.addr)" fi fi echo diff --git a/usr/local/share/bastille/stop.sh b/usr/local/share/bastille/stop.sh index a66d6d07..a191cb52 100644 --- a/usr/local/share/bastille/stop.sh +++ b/usr/local/share/bastille/stop.sh @@ -55,8 +55,10 @@ if [ "${TARGET}" = 'ALL' ]; then fi if [ "${TARGET}" != 'ALL' ]; then JAILS=$(jls name | awk "/^${TARGET}$/") - ## test if not running - if [ ! "$(jls name | awk "/^${TARGET}$/")" ]; then + ## check if exist or not running + if [ ! -d "${bastille_jailsdir}/${TARGET}" ]; then + echo -e "${COLOR_RED}[${TARGET}]: Not found.${COLOR_RESET}" + elif [ ! "$(jls name | awk "/^${TARGET}$/")" ]; then echo -e "${COLOR_RED}[${TARGET}]: Not started.${COLOR_RESET}" fi fi @@ -65,8 +67,8 @@ for _jail in ${JAILS}; do ## test if running if [ "$(jls name | awk "/^${_jail}$/")" ]; then ## remove ip4.addr from firewall table:jails - if [ ! -z "${bastille_jail_loopback}" ]; then - pfctl -q -t jails -T delete $(jls -j ${_jail} ip4.addr) + if [ -n "${bastille_jail_loopback}" ]; then + pfctl -q -t jails -T delete "$(jls -j "${_jail}" ip4.addr)" fi ## remove rctl limits @@ -78,7 +80,7 @@ for _jail in ${JAILS}; do ## stop container echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" - jail -f "${bastille_jailsdir}/${_jail}/jail.conf" -r ${_jail} + jail -f "${bastille_jailsdir}/${_jail}/jail.conf" -r "${_jail}" fi echo done diff --git a/usr/local/share/bastille/sysrc.sh b/usr/local/share/bastille/sysrc.sh index 317d9580..40780a19 100644 --- a/usr/local/share/bastille/sysrc.sh +++ b/usr/local/share/bastille/sysrc.sh @@ -54,11 +54,11 @@ if [ "${TARGET}" = 'ALL' ]; then fi if [ "${TARGET}" != 'ALL' ]; then - JAILS=$(jls name | grep -w "${TARGET}") + JAILS=$(jls name | awk "/^${TARGET}$/") fi for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" - jexec -l ${_jail} /usr/sbin/sysrc $@ + 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 bcd66f59..a54cb242 100644 --- a/usr/local/share/bastille/template.sh +++ b/usr/local/share/bastille/template.sh @@ -54,7 +54,7 @@ if [ "${TARGET}" = 'ALL' ]; then JAILS=$(jls name) fi if [ "${TARGET}" != 'ALL' ]; then - JAILS=$(jls name | grep -w "${TARGET}") + JAILS=$(jls name | awk "/^${TARGET}$/") fi TEMPLATE="${1}" @@ -80,12 +80,12 @@ for _jail in ${JAILS}; do ## TARGET if [ -s "${bastille_template}/TARGET" ]; then - if [ $(grep -w "${_jail}" ${bastille_template}/TARGET) ]; then + if grep -qw "${_jail}" "${bastille_template}/TARGET"; then echo -e "${COLOR_GREEN}TARGET: !${_jail}.${COLOR_RESET}" echo continue fi - if [ ! $(grep -E "(^|\b)(${_jail}|ALL)($|\b)" ${bastille_template}/TARGET) ]; then + if ! grep -Eq "(^|\b)(${_jail}|ALL)($|\b)" "${bastille_template}/TARGET"; then echo -e "${COLOR_GREEN}TARGET: ?${_jail}.${COLOR_RESET}" echo continue @@ -107,7 +107,7 @@ for _jail in ${JAILS}; do _rctl_rule="jail:${_jail}:${_limit_key}:deny=${_limit_value}/jail" ## if entry doesn't exist, add; else show existing entry - if [ ! "$(grep -qs "${_rctl_rule}" "${bastille_jailsdir}/${_jail}/rctl.conf")" ]; then + if ! grep -qs "${_rctl_rule}" "${bastille_jailsdir}/${_jail}/rctl.conf"; then echo "${_rctl_rule}" >> "${bastille_jailsdir}/${_jail}/rctl.conf" echo "${_limits}" else @@ -131,12 +131,12 @@ for _jail in ${JAILS}; do case ${_include} in http?://github.com/*/*|http?://gitlab.com/*/*) - bastille bootstrap ${_include} + bastille bootstrap "${_include}" ;; */*) BASTILLE_TEMPLATE_USER=$(echo "${_include}" | awk -F / '{ print $1 }') BASTILLE_TEMPLATE_REPO=$(echo "${_include}" | awk -F / '{ print $2 }') - bastille template ${_jail} ${BASTILLE_TEMPLATE_USER}/${BASTILLE_TEMPLATE_REPO} + bastille template "${_jail}" "${BASTILLE_TEMPLATE_USER}/${BASTILLE_TEMPLATE_REPO}" ;; *) echo -e "${COLOR_RED}Template INCLUDE content not recognized.${COLOR_RESET}" @@ -148,7 +148,7 @@ for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}Applying ${_include}...${COLOR_RESET}" BASTILLE_TEMPLATE_PROJECT=$(echo "${_include}" | awk -F / '{ print $4}') BASTILLE_TEMPLATE_REPO=$(echo "${_include}" | awk -F / '{ print $5}') - bastille template ${_jail} ${BASTILLE_TEMPLATE_PROJECT}/${BASTILLE_TEMPLATE_REPO} + bastille template "${_jail}" "${BASTILLE_TEMPLATE_PROJECT}/${BASTILLE_TEMPLATE_REPO}" done < "${bastille_template}/INCLUDE" echo -e "${COLOR_GREEN}[${_jail}]:INCLUDE -- END${COLOR_RESET}" echo @@ -157,7 +157,7 @@ for _jail in ${JAILS}; do ## PRE if [ -s "${bastille_template}/PRE" ]; then echo -e "${COLOR_GREEN}[${_jail}]:PRE -- START${COLOR_RESET}" - jexec -l ${_jail} /bin/sh < "${bastille_template}/PRE" || exit 1 + jexec -l "${_jail}" /bin/sh < "${bastille_template}/PRE" || exit 1 echo -e "${COLOR_GREEN}[${_jail}]:PRE -- END${COLOR_RESET}" echo fi @@ -206,11 +206,11 @@ for _jail in ${JAILS}; do _fstab_entry="${_hostpath} ${bastille_jailsdir}/${_jail}/root/${_jailpath} ${_type} ${_perms} ${_checks}" ## if entry doesn't exist, add; else show existing entry - if [ ! "$(grep "${_jailpath}" "${bastille_jailsdir}/${_jail}/fstab")" ]; then + if ! grep -q "${_jailpath}" "${bastille_jailsdir}/${_jail}/fstab"; then echo "${_fstab_entry}" >> "${bastille_jailsdir}/${_jail}/fstab" echo "Added: ${_fstab_entry}" else - echo "$(grep "${_jailpath}" "${bastille_jailsdir}/${_jail}/fstab")" + grep "${_jailpath}" "${bastille_jailsdir}/${_jail}/fstab" fi done < "${bastille_template}/FSTAB" mount -F "${bastille_jailsdir}/${_jail}/fstab" -a @@ -227,7 +227,7 @@ for _jail in ${JAILS}; do if [ -s "${bastille_template}/PKG" ]; then echo -e "${COLOR_GREEN}[${_jail}]:PKG -- START${COLOR_RESET}" jexec -l "${_jail}" env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg bootstrap || exit 1 - jexec -l "${_jail}" env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg install $(cat ${bastille_template}/PKG) || exit 1 + jexec -l "${_jail}" env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg install $(cat "${bastille_template}/PKG") || exit 1 jexec -l "${_jail}" env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg audit -F echo -e "${COLOR_GREEN}[${_jail}]:PKG -- END${COLOR_RESET}" echo @@ -238,7 +238,7 @@ for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}[${_jail}]:OVERLAY -- START${COLOR_RESET}" while read _dir; do cp -av "${bastille_template}/${_dir}" "${bastille_jail_path}" || exit 1 - done < ${bastille_template}/OVERLAY + done < "${bastille_template}/OVERLAY" echo -e "${COLOR_GREEN}[${_jail}]:OVERLAY -- END${COLOR_RESET}" echo fi @@ -247,7 +247,7 @@ for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}[${_jail}]:CONFIG -- START${COLOR_RESET}" while read _dir; do cp -av "${bastille_template}/${_dir}" "${bastille_jail_path}" || exit 1 - done < ${bastille_template}/CONFIG + done < "${bastille_template}/CONFIG" echo -e "${COLOR_GREEN}[${_jail}]:CONFIG -- END${COLOR_RESET}" echo fi @@ -256,7 +256,7 @@ for _jail in ${JAILS}; do if [ -s "${bastille_template}/SYSRC" ]; then echo -e "${COLOR_GREEN}[${_jail}]:SYSRC -- START${COLOR_RESET}" while read _sysrc; do - jexec -l ${_jail} /usr/sbin/sysrc "${_sysrc}" || exit 1 + jexec -l "${_jail}" /usr/sbin/sysrc "${_sysrc}" || exit 1 done < "${bastille_template}/SYSRC" echo -e "${COLOR_GREEN}[${_jail}]:SYSRC -- END${COLOR_RESET}" echo @@ -266,7 +266,7 @@ for _jail in ${JAILS}; do if [ -s "${bastille_template}/SERVICE" ]; then echo -e "${COLOR_GREEN}[${_jail}]:SERVICE -- START${COLOR_RESET}" while read _service; do - jexec -l ${_jail} /usr/sbin/service ${_service} || exit 1 + jexec -l "${_jail}" /usr/sbin/service "${_service}" || exit 1 done < "${bastille_template}/SERVICE" echo -e "${COLOR_GREEN}[${_jail}]:SERVICE -- END${COLOR_RESET}" echo @@ -275,7 +275,7 @@ for _jail in ${JAILS}; do ## CMD if [ -s "${bastille_template}/CMD" ]; then echo -e "${COLOR_GREEN}[${_jail}]:CMD -- START${COLOR_RESET}" - jexec -l ${_jail} /bin/sh < "${bastille_template}/CMD" || exit 1 + jexec -l "${_jail}" /bin/sh < "${bastille_template}/CMD" || exit 1 echo -e "${COLOR_GREEN}[${_jail}]:CMD -- END${COLOR_RESET}" echo fi diff --git a/usr/local/share/bastille/top.sh b/usr/local/share/bastille/top.sh index 9f0cd692..6b1cc7ec 100644 --- a/usr/local/share/bastille/top.sh +++ b/usr/local/share/bastille/top.sh @@ -54,11 +54,11 @@ if [ "${TARGET}" = 'ALL' ]; then fi if [ "${TARGET}" != 'ALL' ]; then - JAILS=$(jls name | grep -w "${TARGET}") + JAILS=$(jls name | awk "/^${TARGET}$/") fi for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" - jexec -l ${_jail} /usr/bin/top + jexec -l "${_jail}" /usr/bin/top echo -e "${COLOR_RESET}" done diff --git a/usr/local/share/bastille/update.sh b/usr/local/share/bastille/update.sh index f9bd827b..5ff3fe1c 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() { - echo -e "${COLOR_RED}Usage: bastille update release | container.${COLOR_RESET}" + echo -e "${COLOR_RED}Usage: bastille update [release|container].${COLOR_RESET}" exit 1 } @@ -50,16 +50,16 @@ fi TARGET="${1}" shift -if [ ! -z "$(freebsd-version | grep -i HBSD)" ]; then +if freebsd-version | grep -qi HBSD; then echo -e "${COLOR_RED}Not yet supported on HardenedBSD.${COLOR_RESET}" exit 1 fi if [ -d "${bastille_jailsdir}/${TARGET}" ]; then if ! grep -qw ".bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then - if [ "$(jls name | grep -w "${TARGET}")" ]; then + if [ "$(jls name | awk "/^${TARGET}$/")" ]; then # Update a thick container. - CURRENT_VERSION=$(/usr/sbin/jexec -l ${TARGET} freebsd-version 2>/dev/null) + CURRENT_VERSION=$(/usr/sbin/jexec -l "${TARGET}" freebsd-version 2>/dev/null) if [ -z "${CURRENT_VERSION}" ]; then echo -e "${COLOR_RED}Can't determine '${TARGET}' version.${COLOR_RESET}" exit 1 diff --git a/usr/local/share/bastille/upgrade.sh b/usr/local/share/bastille/upgrade.sh index 1d43f3be..9441bdc6 100644 --- a/usr/local/share/bastille/upgrade.sh +++ b/usr/local/share/bastille/upgrade.sh @@ -51,7 +51,7 @@ RELEASE="$1" shift NEWRELEASE="$1" -if [ ! -z "$(freebsd-version | grep -i HBSD)" ]; then +if freebsd-version | grep -qi HBSD; then echo -e "${COLOR_RED}Not yet supported on HardenedBSD.${COLOR_RESET}" exit 1 fi diff --git a/usr/local/share/bastille/verify.sh b/usr/local/share/bastille/verify.sh index c6e19cc3..befc574f 100644 --- a/usr/local/share/bastille/verify.sh +++ b/usr/local/share/bastille/verify.sh @@ -37,13 +37,13 @@ bastille_usage() { } verify_release() { - if [ ! -z "$(freebsd-version | grep -i HBSD)" ]; then + if freebsd-version | grep -qi HBSD; then echo -e "${COLOR_RED}Not yet supported on HardenedBSD.${COLOR_RESET}" exit 1 fi if [ -d "${bastille_releasesdir}/${RELEASE}" ]; then - freebsd-update -b "${bastille_releasesdir}/${RELEASE}" --currently-running ${RELEASE} IDS + freebsd-update -b "${bastille_releasesdir}/${RELEASE}" --currently-running "${RELEASE}" IDS else echo -e "${COLOR_RED}${RELEASE} not found. See bootstrap.${COLOR_RESET}" exit 1 @@ -61,7 +61,7 @@ verify_template() { echo -e "${COLOR_GREEN}Detected ${_hook} hook.${COLOR_RESET}" ## line count must match newline count - if [ $(wc -l ${_path} | awk '{print $1}') -ne $(grep -c $'\n' ${_path}) ]; then + if [ $(wc -l "${_path}" | awk '{print $1}') -ne $(grep -c $'\n' "${_path}") ]; then echo -e "${COLOR_GREEN}[${_hook}]:${COLOR_RESET}" echo -e "${COLOR_RED}${BASTILLE_TEMPLATE}:${_hook} [failed].${COLOR_RESET}" echo -e "${COLOR_RED}Line numbers don't match line breaks.${COLOR_RESET}" @@ -79,19 +79,19 @@ verify_template() { case ${_include} in http?://github.com/*/*|http?://gitlab.com/*/*) - bastille bootstrap ${_include} + bastille bootstrap "${_include}" ;; */*) BASTILLE_TEMPLATE_USER=$(echo "${_include}" | awk -F / '{ print $1 }') BASTILLE_TEMPLATE_REPO=$(echo "${_include}" | awk -F / '{ print $2 }') - bastille verify ${BASTILLE_TEMPLATE_USER}/${BASTILLE_TEMPLATE_REPO} + bastille verify "${BASTILLE_TEMPLATE_USER}/${BASTILLE_TEMPLATE_REPO}" ;; *) echo -e "${COLOR_RED}Template INCLUDE content not recognized.${COLOR_RESET}" exit 1 ;; esac - done < ${_path} + done < "${_path}" ## if tree; tree -a bastille_template/_dir elif [ ${_hook} = 'OVERLAY' ]; then @@ -101,12 +101,12 @@ verify_template() { while read _dir; do echo -e "${COLOR_GREEN}[${_hook}]:[${_dir}]:${COLOR_RESET}" if [ -x /usr/local/bin/tree ]; then - /usr/local/bin/tree -a ${_template_path}/${_dir} + /usr/local/bin/tree -a "${_template_path}/${_dir}" else find "${_template_path}/${_dir}" -print | sed -e 's;[^/]*/;|___;g;s;___|; |;g' fi echo - done < ${_path} + done < "${_path}" else echo -e "${COLOR_GREEN}[${_hook}]:${COLOR_RESET}" cat "${_path}" @@ -119,7 +119,7 @@ verify_template() { if [ ${_hook_validate} -lt 1 ]; then echo -e "${COLOR_RED}No valid template hooks found.${COLOR_RESET}" echo -e "${COLOR_RED}Template discarded.${COLOR_RESET}" - rm -rf ${bastille_template} + rm -rf "${bastille_template}" exit 1 fi diff --git a/usr/local/share/bastille/zfs.sh b/usr/local/share/bastille/zfs.sh index 32d46363..c2120c0e 100644 --- a/usr/local/share/bastille/zfs.sh +++ b/usr/local/share/bastille/zfs.sh @@ -39,7 +39,7 @@ usage() { zfs_snapshot() { for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" - zfs snapshot ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}@${TAG} + zfs snapshot "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}"@"${TAG}" echo done } @@ -47,7 +47,7 @@ done zfs_set_value() { for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" - zfs $ATTRIBUTE ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail} + zfs "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" echo done } @@ -55,7 +55,7 @@ done zfs_get_value() { for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" - zfs get $ATTRIBUTE ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail} + zfs get "${ATTRIBUTE}" "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" echo done } @@ -63,7 +63,7 @@ done zfs_disk_usage() { for _jail in ${JAILS}; do echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" - zfs list -t all -o name,used,avail,refer,mountpoint,compress,ratio -r ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail} + zfs list -t all -o name,used,avail,refer,mountpoint,compress,ratio -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${_jail}" echo done } @@ -98,7 +98,7 @@ if [ "${TARGET}" = 'ALL' ]; then fi if [ "${TARGET}" != 'ALL' ]; then - JAILS=$(jls name | grep -w "${TARGET}") + JAILS=$(jls name | awk "/^${TARGET}$/") fi case "$2" in diff --git a/usr/local/share/man/man1/bastille.1.gz b/usr/local/share/man/man1/bastille.1.gz new file mode 100644 index 00000000..a09110d4 Binary files /dev/null and b/usr/local/share/man/man1/bastille.1.gz differ diff --git a/usr/share/man/man1/bastille.1.gz b/usr/share/man/man1/bastille.1.gz deleted file mode 100644 index 5356fa58..00000000 Binary files a/usr/share/man/man1/bastille.1.gz and /dev/null differ