Merge pull request #78 from cedwards/template_work

template validation improvements
This commit is contained in:
Christer Edwards
2019-12-07 17:57:03 -07:00
committed by GitHub
4 changed files with 186 additions and 144 deletions

View File

@@ -1,9 +1,9 @@
Bastille: Automated Container Security Bastille: Automate Container Security
====================================== =====================================
Bastille is an open-source system for automating deployment and management of [Bastille](https://bastillebsd.org/) is an open-source system for automating
containerized applications on FreeBSD. deployment and management of containerized applications on FreeBSD.
Looking for [Bastille Templates](https://gitlab.com/BastilleBSD-Templates)? Looking for [Bastille Templates](https://gitlab.com/BastilleBSD-Templates/)?
Installation Installation
@@ -557,9 +557,9 @@ To leverage a template hook, create an UPPERCASE file in the root of the
template directory named after the hook you want to execute. eg; template directory named after the hook you want to execute. eg;
```shell ```shell
echo "install zsh vim-console git-lite htop" > /usr/local/bastille/templates/base/PKG echo "zsh vim-console git-lite htop" > /usr/local/bastille/templates/username/base/PKG
echo "/usr/bin/chsh -s /usr/local/bin/zsh" > /usr/local/bastille/templates/base/CMD echo "/usr/bin/chsh -s /usr/local/bin/zsh" > /usr/local/bastille/templates/username/base/CMD
echo "etc\nroot\nusr" > /usr/local/bastille/templates/base/OVERLAY echo "usr" > /usr/local/bastille/templates/username/base/OVERLAY
``` ```
Template hooks are executed in specific order and require specific syntax to Template hooks are executed in specific order and require specific syntax to

View File

@@ -360,74 +360,21 @@ bootstrap_template() {
_template=${bastille_templatesdir}/${_user}/${_repo} _template=${bastille_templatesdir}/${_user}/${_repo}
## support for non-git ## support for non-git
if [ ! -x /usr/local/bin/git ]; then if [ ! -x $(which git) ]; then
echo -e "${COLOR_RED}We're gonna have to use fetch. Strap in.${COLOR_RESET}" echo -e "${COLOR_RED}Git not found.${COLOR_RESET}"
echo -e "${COLOR_RED}Not yet implemented...${COLOR_RESET}" echo -e "${COLOR_RED}Not yet implemented.${COLOR_RESET}"
exit 1 exit 1
fi elif [ -x $(which git) ]; then
## support for git
if [ -x /usr/local/bin/git ]; then
if [ ! -d "${_template}/.git" ]; then if [ ! -d "${_template}/.git" ]; then
/usr/local/bin/git clone "${_url}" "${_template}" ||\ $(which git) clone "${_url}" "${_template}" ||\
echo -e "${COLOR_RED}Clone unsuccessful.${COLOR_RESET}" echo -e "${COLOR_RED}Clone unsuccessful.${COLOR_RESET}"
echo
elif [ -d "${_template}/.git" ]; then elif [ -d "${_template}/.git" ]; then
cd ${_template} && cd ${_template} && $(which git) pull ||\
/usr/local/bin/git pull ||\
echo -e "${COLOR_RED}Template update unsuccessful.${COLOR_RESET}" echo -e "${COLOR_RED}Template update unsuccessful.${COLOR_RESET}"
echo
fi fi
fi fi
## template validation bastille verify ${_user}/${_repo}
_hook_validate=0
for _hook in PRE FSTAB PF PKG SYSRC CMD; do
if [ -s ${_template}/${_hook} ]; then
_hook_validate=$((_hook_validate+1))
echo -e "${COLOR_GREEN}Detected ${_hook} hook.${COLOR_RESET}"
echo -e "${COLOR_GREEN}[${_hook}]:${COLOR_RESET}"
cat "${_template}/${_hook}"
echo
fi
done
# template overlay
if [ -s ${_template}/OVERLAY ]; then
_hook_validate=$((_hook_validate+1))
echo -e "${COLOR_GREEN}Detected OVERLAY hook.${COLOR_RESET}"
while read _dir; do
echo -e "${COLOR_GREEN}[${_dir}]:${COLOR_RESET}"
if [ -x $(which tree) ]; then
tree -a ${_template}/${_dir}
fi
done < ${_template}/OVERLAY
echo
fi
if [ -s ${_template}/CONFIG ]; then
echo -e "${COLOR_GREEN}Detected CONFIG hook.${COLOR_RESET}"
echo -e "${COLOR_YELLOW}CONFIG deprecated; rename to OVERLAY.${COLOR_RESET}"
while read _dir; do
echo -e "${COLOR_GREEN}[${_dir}]:${COLOR_RESET}"
if [ -x $(which tree) ]; then
tree -a ${_template}/${_dir}
fi
done < ${_template}/CONFIG
fi
## remove bad templates
if [ ${_hook_validate} -lt 1 ]; then
echo -e "${COLOR_GREEN}Template validation failed.${COLOR_RESET}"
echo -e "${COLOR_GREEN}Deleting template.${COLOR_RESET}"
rm -rf ${_template}
exit 1
fi
## if validated; ready to use
if [ ${_hook_validate} -gt 0 ]; then
echo -e "${COLOR_GREEN}Template ready to use.${COLOR_RESET}"
echo
fi
} }
HW_MACHINE=$(sysctl hw.machine | awk '{ print $2 }') HW_MACHINE=$(sysctl hw.machine | awk '{ print $2 }')
@@ -486,8 +433,6 @@ http?://github.com/*/*|http?://gitlab.com/*/*)
BASTILLE_TEMPLATE_URL=${1} BASTILLE_TEMPLATE_URL=${1}
BASTILLE_TEMPLATE_USER=$(echo "${1}" | awk -F / '{ print $4 }') BASTILLE_TEMPLATE_USER=$(echo "${1}" | awk -F / '{ print $4 }')
BASTILLE_TEMPLATE_REPO=$(echo "${1}" | awk -F / '{ print $5 }') BASTILLE_TEMPLATE_REPO=$(echo "${1}" | awk -F / '{ print $5 }')
echo -e "${COLOR_GREEN}Template: ${1}${COLOR_RESET}"
echo
bootstrap_template bootstrap_template
;; ;;
network) network)

View File

@@ -31,7 +31,7 @@
. /usr/local/share/bastille/colors.pre.sh . /usr/local/share/bastille/colors.pre.sh
. /usr/local/etc/bastille/bastille.conf . /usr/local/etc/bastille/bastille.conf
usage() { bastille_usage() {
echo -e "${COLOR_RED}Usage: bastille template TARGET project/template.${COLOR_RESET}" echo -e "${COLOR_RED}Usage: bastille template TARGET project/template.${COLOR_RESET}"
exit 1 exit 1
} }
@@ -39,12 +39,12 @@ usage() {
# Handle special-case commands first. # Handle special-case commands first.
case "$1" in case "$1" in
help|-h|--help) help|-h|--help)
usage bastille_usage
;; ;;
esac esac
if [ $# -gt 2 ] || [ $# -lt 2 ]; then if [ $# -gt 2 ] || [ $# -lt 2 ]; then
usage bastille_usage
fi fi
TARGET="${1}" TARGET="${1}"
@@ -60,24 +60,13 @@ fi
TEMPLATE="${1}" TEMPLATE="${1}"
shift shift
if [ ! -d "${bastille_templatesdir}"/"${TEMPLATE}" ]; then if [ ! -d "${bastille_templatesdir}/${TEMPLATE}" ]; then
echo -e "${COLOR_RED}${TEMPLATE} not found.${COLOR_RESET}" echo -e "${COLOR_RED}${TEMPLATE} not found.${COLOR_RESET}"
exit 1 exit 1
fi fi
## global variables ## global variables
bastille_template=${bastille_templatesdir}/${TEMPLATE} bastille_template=${bastille_templatesdir}/${TEMPLATE}
bastille_template_TARGET=${bastille_template}/TARGET
bastille_template_INCLUDE=${bastille_template}/INCLUDE
bastille_template_PRE=${bastille_template}/PRE
bastille_template_OVERLAY=${bastille_template}/OVERLAY
bastille_template_FSTAB=${bastille_template}/FSTAB
bastille_template_PF=${bastille_template}/PF
bastille_template_PKG=${bastille_template}/PKG
bastille_template_SYSRC=${bastille_template}/SYSRC
bastille_template_SERVICE=${bastille_template}/SERVICE
bastille_template_CMD=${bastille_template}/CMD
for _jail in ${JAILS}; do for _jail in ${JAILS}; do
## jail-specific variables. ## jail-specific variables.
bastille_jail_path=$(jls -j "${_jail}" path) bastille_jail_path=$(jls -j "${_jail}" path)
@@ -85,13 +74,13 @@ for _jail in ${JAILS}; do
echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}" echo -e "${COLOR_GREEN}[${_jail}]:${COLOR_RESET}"
## TARGET ## TARGET
if [ -s "${bastille_template_TARGET}" ]; then if [ -s "${bastille_template}/TARGET" ]; then
if [ $(grep -w "${_jail}" ${bastille_template_TARGET}) ]; then if [ $(grep -w "${_jail}" ${bastille_template}/TARGET) ]; then
echo -e "${COLOR_GREEN}TARGET: !${_jail}.${COLOR_RESET}" echo -e "${COLOR_GREEN}TARGET: !${_jail}.${COLOR_RESET}"
echo echo
continue continue
fi fi
if [ ! $(grep -E "(^|\b)(${_jail}|ALL)($|\b)" ${bastille_template_TARGET}) ]; then if [ ! $(grep -E "(^|\b)(${_jail}|ALL)($|\b)" ${bastille_template}/TARGET) ]; then
echo -e "${COLOR_GREEN}TARGET: ?${_jail}.${COLOR_RESET}" echo -e "${COLOR_GREEN}TARGET: ?${_jail}.${COLOR_RESET}"
echo echo
continue continue
@@ -99,38 +88,72 @@ for _jail in ${JAILS}; do
fi fi
## INCLUDE ## INCLUDE
if [ -s "${bastille_template_INCLUDE}" ]; then if [ -s "${bastille_template}/INCLUDE" ]; then
echo -e "${COLOR_GREEN}[${_jail}]:INCLUDE -- START${COLOR_RESET}" echo -e "${COLOR_GREEN}[${_jail}]:INCLUDE -- START${COLOR_RESET}"
while read _include; do while read _include; do
echo echo
echo -e "${COLOR_GREEN}INCLUDE: ${_include}${COLOR_RESET}" echo -e "${COLOR_GREEN}INCLUDE: ${_include}${COLOR_RESET}"
echo -e "${COLOR_GREEN}Bootstrapping ${_include}...${COLOR_RESET}" echo -e "${COLOR_GREEN}Bootstrapping ${_include}...${COLOR_RESET}"
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}
;;
*)
echo -e "${COLOR_RED}Template INCLUDE content not recognized.${COLOR_RESET}"
exit 1
;;
esac
echo echo
echo -e "${COLOR_GREEN}Applying ${_include}...${COLOR_RESET}" echo -e "${COLOR_GREEN}Applying ${_include}...${COLOR_RESET}"
BASTILLE_TEMPLATE_PROJECT=$(echo "${_include}" | awk -F / '{ print $4}') BASTILLE_TEMPLATE_PROJECT=$(echo "${_include}" | awk -F / '{ print $4}')
BASTILLE_TEMPLATE_REPO=$(echo "${_include}" | awk -F / '{ print $5}') 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}" done < "${bastille_template}/INCLUDE"
echo -e "${COLOR_GREEN}[${_jail}]:INCLUDE -- END${COLOR_RESET}" echo -e "${COLOR_GREEN}[${_jail}]:INCLUDE -- END${COLOR_RESET}"
echo echo
fi fi
## PRE ## PRE
if [ -s "${bastille_template_PRE}" ]; then if [ -s "${bastille_template}/PRE" ]; then
echo -e "${COLOR_GREEN}[${_jail}]:PRE -- START${COLOR_RESET}" 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 -e "${COLOR_GREEN}[${_jail}]:PRE -- END${COLOR_RESET}"
echo echo
fi fi
## FSTAB
if [ -s "${bastille_template}/FSTAB" ]; then
echo -e "${COLOR_GREEN}NOT YET IMPLEMENTED.${COLOR_RESET}"
fi
## PF
if [ -s "${bastille_template}/PF" ]; then
echo -e "${COLOR_GREEN}NOT YET IMPLEMENTED.${COLOR_RESET}"
fi
## PKG (bootstrap + pkg)
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 audit -F
echo -e "${COLOR_GREEN}[${_jail}]:PKG -- END${COLOR_RESET}"
echo
fi
## CONFIG / OVERLAY ## CONFIG / OVERLAY
if [ -s "${bastille_template_OVERLAY}" ]; then if [ -s "${bastille_template}/OVERLAY" ]; then
echo -e "${COLOR_GREEN}[${_jail}]:OVERLAY -- START${COLOR_RESET}" echo -e "${COLOR_GREEN}[${_jail}]:OVERLAY -- START${COLOR_RESET}"
while read _dir; do while read _dir; do
cp -av "${bastille_template}/${_dir}" "${bastille_jail_path}" || exit 1 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 -e "${COLOR_GREEN}[${_jail}]:OVERLAY -- END${COLOR_RESET}"
echo echo
fi fi
@@ -144,54 +167,30 @@ for _jail in ${JAILS}; do
echo echo
fi fi
## FSTAB
if [ -s "${bastille_template_FSTAB}" ]; then
bastille_templatefstab=$(cat "${bastille_template_FSTAB}")
echo -e "${COLOR_GREEN}Updating fstab.${COLOR_RESET}"
echo -e "${COLOR_GREEN}NOT YET IMPLEMENTED.${COLOR_RESET}"
fi
## PF
if [ -s "${bastille_template_PF}" ]; then
bastille_templatepf=$(cat "${bastille_template_PF}")
echo -e "${COLOR_GREEN}Generating PF profile.${COLOR_RESET}"
echo -e "${COLOR_GREEN}NOT YET IMPLEMENTED.${COLOR_RESET}"
fi
## PKG (bootstrap + pkg)
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 audit -F
jexec -l "${_jail}" env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg install $(cat ${bastille_template_PKG}) || exit 1
echo -e "${COLOR_GREEN}[${_jail}]:PKG -- END${COLOR_RESET}"
echo
fi
## SYSRC ## SYSRC
if [ -s "${bastille_template_SYSRC}" ]; then if [ -s "${bastille_template}/SYSRC" ]; then
echo -e "${COLOR_GREEN}[${_jail}]:SYSRC -- START${COLOR_RESET}" echo -e "${COLOR_GREEN}[${_jail}]:SYSRC -- START${COLOR_RESET}"
while read _sysrc; do 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}" done < "${bastille_template}/SYSRC"
echo -e "${COLOR_GREEN}[${_jail}]:SYSRC -- END${COLOR_RESET}" echo -e "${COLOR_GREEN}[${_jail}]:SYSRC -- END${COLOR_RESET}"
echo echo
fi fi
## SERVICE ## SERVICE
if [ -s "${bastille_template_SERVICE}" ]; then if [ -s "${bastille_template}/SERVICE" ]; then
echo -e "${COLOR_GREEN}[${_jail}]:SERVICE -- START${COLOR_RESET}" echo -e "${COLOR_GREEN}[${_jail}]:SERVICE -- START${COLOR_RESET}"
while read _service; do 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}" done < "${bastille_template}/SERVICE"
echo -e "${COLOR_GREEN}[${_jail}]:SERVICE -- END${COLOR_RESET}" echo -e "${COLOR_GREEN}[${_jail}]:SERVICE -- END${COLOR_RESET}"
echo echo
fi fi
## CMD ## CMD
if [ -s "${bastille_template_CMD}" ]; then if [ -s "${bastille_template}/CMD" ]; then
echo -e "${COLOR_GREEN}[${_jail}]:CMD -- START${COLOR_RESET}" 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 -e "${COLOR_GREEN}[${_jail}]:CMD -- END${COLOR_RESET}"
echo echo
fi fi

View File

@@ -31,32 +31,130 @@
. /usr/local/share/bastille/colors.pre.sh . /usr/local/share/bastille/colors.pre.sh
. /usr/local/etc/bastille/bastille.conf . /usr/local/etc/bastille/bastille.conf
usage() { bastille_usage() {
echo -e "${COLOR_RED}Usage: bastille verify release.${COLOR_RESET}" echo -e "${COLOR_RED}Usage: bastille verify [release|template].${COLOR_RESET}"
exit 1 exit 1
} }
# Handle special-case commands first. verify_release() {
case "$1" in
help|-h|--help)
usage
;;
esac
if [ $# -gt 1 ] || [ $# -lt 1 ]; then
usage
fi
RELEASE=$1
if [ ! -z "$(freebsd-version | grep -i HBSD)" ]; then if [ ! -z "$(freebsd-version | grep -i HBSD)" ]; then
echo -e "${COLOR_RED}Not yet supported on HardenedBSD.${COLOR_RESET}" echo -e "${COLOR_RED}Not yet supported on HardenedBSD.${COLOR_RESET}"
exit 1 exit 1
fi fi
if [ -d "${bastille_releasesdir}/${RELEASE}" ]; then if [ -d "${bastille_releasesdir}/${RELEASE}" ]; then
freebsd-update -b "${bastille_releasesdir}/${RELEASE}" IDS freebsd-update -b "${bastille_releasesdir}/${RELEASE}" --currently-running ${RELEASE} IDS
else else
echo -e "${COLOR_RED}${RELEASE} not found. See bootstrap.${COLOR_RESET}" echo -e "${COLOR_RED}${RELEASE} not found. See bootstrap.${COLOR_RESET}"
exit 1 exit 1
fi fi
}
verify_template() {
_template_path=${bastille_templatesdir}/${BASTILLE_TEMPLATE}
_hook_validate=0
for _hook in TARGET INCLUDE PRE OVERLAY FSTAB PF PKG SYSRC SERVICE CMD; do
_path=${_template_path}/${_hook}
if [ -s ${_path} ]; then
_hook_validate=$((_hook_validate+1))
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
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}"
echo
echo -e "${COLOR_RED}Template validation failed.${COLOR_RESET}"
exit 1
## if INCLUDE; recursive verify
elif [ ${_hook} = 'INCLUDE' ]; then
echo -e "${COLOR_GREEN}[${_hook}]:${COLOR_RESET}"
cat "${_path}"
echo
while read _include; do
echo -e "${COLOR_GREEN}[${_hook}]:[${_include}]:${COLOR_RESET}"
case ${_include} in
http?://github.com/*/*|http?://gitlab.com/*/*)
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}
;;
*)
echo -e "${COLOR_RED}Template INCLUDE content not recognized.${COLOR_RESET}"
exit 1
;;
esac
done < ${_path}
## if tree; tree -a bastille_template/_dir
elif [ ${_hook} = 'OVERLAY' ]; then
echo -e "${COLOR_GREEN}[${_hook}]:${COLOR_RESET}"
cat "${_path}"
echo
while read _dir; do
if [ -x /usr/local/bin/tree ]; then
echo -e "${COLOR_GREEN}[${_hook}]:[${_dir}]:${COLOR_RESET}"
tree -a ${_template_path}/${_dir}
echo
fi
done < ${_path}
else
echo -e "${COLOR_GREEN}[${_hook}]:${COLOR_RESET}"
cat "${_path}"
echo
fi
fi
done
## remove bad templates
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}
exit 1
fi
## if validated; ready to use
if [ ${_hook_validate} -gt 0 ]; then
echo -e "${COLOR_GREEN}Template ready to use.${COLOR_RESET}"
fi
}
# Handle special-case commands first.
case "$1" in
help|-h|--help)
bastille_usage
;;
esac
if [ $# -gt 1 ] || [ $# -lt 1 ]; then
bastille_usage
fi
case "$1" in
*-RELEASE|*-release|*-RC1|*-rc1|*-RC2|*-rc2)
RELEASE=$1
verify_release
;;
*-stable-LAST|*-STABLE-last|*-stable-last|*-STABLE-LAST)
RELEASE=$1
verify_release
;;
http?*)
bastille_usage
;;
*/*)
BASTILLE_TEMPLATE=$1
verify_template
;;
*)
bastille_usage
;;
esac