diff --git a/LICENSE b/LICENSE index 0dd7171..d3e2f90 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2018, BastilleBSD +Copyright (c) 2018, Christer Edwards All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.md b/README.md index 3edeb88..e6fb5d4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ -# bastille +# Bastille Bastille Jail Management Tool + +README pending; still a little bit in flux. diff --git a/bastille-0.1.txz b/bastille-0.1.txz new file mode 100644 index 0000000..6504d95 Binary files /dev/null and b/bastille-0.1.txz differ diff --git a/init.freebsd b/init.freebsd new file mode 100644 index 0000000..bc50ec6 --- /dev/null +++ b/init.freebsd @@ -0,0 +1,65 @@ +#!/bin/sh + +# $FreeBSD: $ +# +# Bastille startup script +# +# PROVIDE: bastille +# REQUIRE: LOGIN +# KEYWORD: shutdown + +# Add the following to /etc/rc.conf[.local] to enable this service +# +# bastille_enable (bool): Set to NO by default. +# Set it to YES to enable bastille. +# bastille_list (string): Set to "" by default. +# Space separated list of jails to start. +# + +. /etc/rc.subr + +name=bastille +rcvar=bastille_enable + +load_rc_config ${name} + +: ${bastille_enable:=NO} +: ${bastille_list:=""} + +start_cmd=bastille_start +stop_cmd=bastille_stop + +start_command="/usr/local/bin/bbsd-start" +stop_command="/usr/local/bin/bbsd-stop" + +bastille_start() +{ + if [ ! -n "${bastille_list}" ]; then + echo "${bastille_list} is undefined" + return 1 + fi + + local _jail + + for _jail in ${bastille_list}; do + echo "Starting Bastille Jail: ${_jail}" + ${start_command} ${_jail} + done +} + +bastille_stop() +{ + if [ ! -n "${bastille_list}" ]; then + echo "${bastille_list} is undefined" + return 1 + fi + + local _jail + + for _jail in ${bastille_list}; do + echo "Stopping Bastille Jail: ${_jail}" + ${stop_command} ${_jail} + done +} + +run_rc_command "$1" diff --git a/usr/local/bin/bbsd-bootstrap b/usr/local/bin/bbsd-bootstrap new file mode 100755 index 0000000..1ca97e0 --- /dev/null +++ b/usr/local/bin/bbsd-bootstrap @@ -0,0 +1,69 @@ +#!/bin/sh + +if [ "$#" -lt 3 ]; then + echo "Required: '[activate|update|snapshot]', 'bastille', 'release'" + echo "Supported releases: '11.1-RELEASE', '10.4-RELEASE', '10.3-RELEASE'" + exit 1 +fi + +echo +echo "###########################" +echo "## args: $1 ##" +echo "## args: $2 ##" +echo "## args: $3 ##" +echo "###########################" +echo + +RELEASE="$3" +PREFIX=/usr/local +PLATFORM="${PREFIX}/$2" +VALIDRELEASE='' + +if [ "${RELEASE}" == "11.1-RELEASE" -o "${RELEASE}" == "10.4-RELEASE" -o "${RELEASE}" == "10.3-RELEASE" ]; then + VALIDRELEASE="${RELEASE}" +fi + +BASETXZPATH="${PLATFORM}/downloads/${RELEASE}/base.txz" +UPSTREAMURL="https://download.freebsd.org/ftp/releases/amd64/${RELEASE}/base.txz" + +if [ "$1" == "activate" ]; then + if [ -d "/usr/local/bastille" ]; then + echo "Looks like you're already bootstrapped." + exit 1 + else + /sbin/zfs create -o compression=lz4 -o atime=off -o mountpoint="${PLATFORM}" "zroot${PLATFORM}" + /sbin/zfs create -o compression=lz4 -o atime=off -o mountpoint="${PLATFORM}/downloads" "zroot${PLATFORM}/downloads" + /sbin/zfs create -o compression=lz4 -o atime=off -o mountpoint="${PLATFORM}/jails" "zroot${PLATFORM}/jails" + /sbin/zfs create -o compression=lz4 -o atime=off -o mountpoint="${PLATFORM}/logs" "zroot${PLATFORM}/logs" + /sbin/zfs create -o compression=lz4 -o atime=off -o mountpoint="${PLATFORM}/fstab" "zroot${PLATFORM}/fstab" + /sbin/zfs create -o compression=lz4 -o atime=off -o mountpoint="${PLATFORM}/releases" "zroot${PLATFORM}/releases" + + ## create the downloads && releases ZFS volumes + if [ ! -z "${VALIDRELEASE}" ]; then + if [ ! -d "${PLATFORM}"/downloads/"${RELEASE}" ]; then + /sbin/zfs create zroot"${PLATFORM}"/downloads/"${RELEASE}" + fi + if [ ! -d "${PLATFORM}"/releases/"${RELEASE}" ]; then + /sbin/zfs create zroot"${PLATFORM}"/releases/"${RELEASE}" + fi + + ## fetch && untar base.txz + if [ ! -f "${BASETXZPATH}" ]; then + /usr/bin/fetch "${UPSTREAMURL}" -o "${PLATFORM}/downloads/${RELEASE}" + /usr/bin/tar -C "${PLATFORM}/releases/${RELEASE}" -xf "${PLATFORM}/downloads/${RELEASE}/base.txz" + fi + + ## freebsd-update && snapshot + env PAGER=/bin/cat /usr/sbin/freebsd-update -b "${PLATFORM}/releases/${RELEASE}" fetch install + /sbin/zfs snapshot "zroot${PLATFORM}/releases/${RELEASE}@$(date +%F)" + fi + fi +fi + +if [ "$1" == "update" ]; then + env PAGER=/bin/cat /usr/sbin/freebsd-update -b "${PLATFORM}/releases/${RELEASE}" fetch install +fi + +if [ "$1" == "snapshot" ]; then + /sbin/zfs snapshot "zroot${PLATFORM}/releases/${RELEASE}@$(date +%F)" +fi diff --git a/usr/local/bin/bbsd-cmd b/usr/local/bin/bbsd-cmd new file mode 100755 index 0000000..8544696 --- /dev/null +++ b/usr/local/bin/bbsd-cmd @@ -0,0 +1,31 @@ +#!/bin/sh +# +# basic cmd targeting and execution + +if [ $# -gt 2 ] || [ $# -lt 2 ]; then + echo "Usage: bbsd-cmd [glob|ALL] 'quoted command'" + exit 1 +fi + +if [ "$1" = 'ALL' ]; then + JAILS=$(jls -N | awk '!/JID/{print $1}') + echo "Targeting all containers." + echo + for jail in ${JAILS}; do + echo "${jail}:" + jexec ${jail} $2 + echo + done +fi + +if [ "$1" != 'ALL' ]; then + JAILS=$(jls -N | awk '!/JID/{print $1}' | grep "$1") + echo "Targeting specified containers." + echo "${JAILS}" + echo + for jail in ${JAILS}; do + echo "${jail}:" + jexec ${jail} $2 + echo + done +fi diff --git a/usr/local/bin/bbsd-create b/usr/local/bin/bbsd-create new file mode 100755 index 0000000..990b81b --- /dev/null +++ b/usr/local/bin/bbsd-create @@ -0,0 +1,74 @@ +#!/bin/sh -x +# +# create a new jail + +if [ $# -lt 3 ] || [ $# -gt 3 ]; then + echo "Required: name repo release." + exit 1 +fi + +NAME="$1" +TEMPLATE="$2" +RELEASE="$3" + +PREFIX=/usr/local +BASTILLE=${PREFIX}/bastille +JAIL_BASE=${BASTILLE}/jails/${NAME} + +JAIL_ROOT=${JAIL_BASE}/root +JAIL_CONF=${JAIL_BASE}/jail.conf +PKGS_CONF=${JAIL_BASE}/pkgs.conf +JAIL_JID=${JAIL_BASE}/${jail}.jid +JAIL_FSTAB="${BASTILLE}/fstab/${NAME}.fstab" +BASEJAIL="${BASTILLE}/releases/${RELEASE}" + +## create zfs volume +if [ ! -d ${JAIL_ROOT} ]; then + echo "Creating Jail Base..." + zfs create -o mountpoint=${JAIL_BASE}\ + -o compression=lz4\ + -o atime=off zroot"${JAIL_BASE}"\ + && echo "Created ZFS volume for jail...[OK]." || echo "Failure: ZFS volume creation." +fi + +## clone template into volume +if [ $(find "${JAIL_BASE}" -empty) ]; then + echo "Cloning template..." + git clone "${TEMPLATE}" "${JAIL_BASE}" || echo "Template cloning failed; exiting" + echo "Cloning release contents..." + /bin/cp -an "${BASEJAIL}/etc" "${JAIL_ROOT}" + /bin/cp -an "${BASEJAIL}/root" "${JAIL_ROOT}" +fi + +## create fstab; IMPORTANT that this goes before pkgs (below) +if [ ! -f ${JAIL_FSTAB} ]; then + /bin/cat << EOF > ${JAIL_FSTAB} +${BASEJAIL}/bin ${JAIL_ROOT}/bin nullfs ro 0 0 +${BASEJAIL}/boot ${JAIL_ROOT}/boot nullfs ro 0 0 +${BASEJAIL}/lib ${JAIL_ROOT}/lib nullfs ro 0 0 +${BASEJAIL}/libexec ${JAIL_ROOT}/libexec nullfs ro 0 0 +${BASEJAIL}/rescue ${JAIL_ROOT}/rescue nullfs ro 0 0 +${BASEJAIL}/sbin ${JAIL_ROOT}/sbin nullfs ro 0 0 +${BASEJAIL}/usr/bin ${JAIL_ROOT}/usr/bin nullfs ro 0 0 +${BASEJAIL}/usr/include ${JAIL_ROOT}/usr/include nullfs ro 0 0 +${BASEJAIL}/usr/lib ${JAIL_ROOT}/usr/lib nullfs ro 0 0 +${BASEJAIL}/usr/libexec ${JAIL_ROOT}/usr/libexec nullfs ro 0 0 +${BASEJAIL}/usr/sbin ${JAIL_ROOT}/usr/sbin nullfs ro 0 0 +${BASEJAIL}/usr/share ${JAIL_ROOT}/usr/share nullfs ro 0 0 +${BASEJAIL}/usr/libdata ${JAIL_ROOT}/usr/libdata nullfs ro 0 0 +EOF +echo "Writing jail fstab (basejail)...[OK]" +fi + +## install pkgs +if [ -s ${PKGS_CONF} ]; then + echo "Starting jail; installing pkgs..." + jail -c -f "${JAIL_CONF}" -J "${JAIL_JID}" ${NAME} + pfctl -f /etc/pf.conf + pkg -j ${NAME} install -y $(cat ${PKGS_CONF}) + jail -r -f "${JAIL_CONF}" ${NAME} + echo "Stopping jail; installation complete." +elif [ ! -s ${PKGS_CONF} ]; then + echo "pkgs.conf appears empty; not installing anything." + echo "complete" +fi diff --git a/usr/local/bin/bbsd-destroy b/usr/local/bin/bbsd-destroy new file mode 100755 index 0000000..f270e5c --- /dev/null +++ b/usr/local/bin/bbsd-destroy @@ -0,0 +1,40 @@ +#!/bin/sh +# +# destroy an existing jail + +JAIL_NAME=$1 +JAIL_PATH=$2 +PREFIX=/usr/local +JLS_NAME="/usr/sbin/jls name" +JLS_PATH="/usr/sbin/jls path" +PLATFORM=${PREFIX}/bastille +FSTAB_PATH=${PLATFORM}/fstab/$1.fstab +JAIL_PATH=${PLATFORM}/jails/$1 + +if [ $# -lt 2 ]; then + echo "Required: name path." + return 1 +fi + +if [ ! -d ${JAIL_PATH} ]; then + echo "Path (${JAIL_PATH}) not found." + return 1 +fi + +if [ $(${JLS_NAME} | grep ${JAIL_NAME}) ]; then + echo "Jail is running." + echo "Stop jail first with bbsd-stop ${JAIL_NAME}." + return 1 +fi + +if [ $(${JLS_PATH} | grep ${JAIL_PATH}) ]; then + echo "Jail is running." + echo "Stop jail first with bbsd-stop ${JAIL_NAME}." + return 1 +fi + +if [ -d ${JAIL_PATH} ]; then + zfs destroy -r zroot${JAIL_PATH} || echo "Unable to destroy zroot${JAIL_PATH}." + rm -rf ${JAIL_PATH} || echo "Unable to delete ${JAIL_PATH}." + echo "Jail destroyed. RIP." +fi diff --git a/usr/local/bin/bbsd-init-repo b/usr/local/bin/bbsd-init-repo new file mode 100755 index 0000000..3c1f1ba --- /dev/null +++ b/usr/local/bin/bbsd-init-repo @@ -0,0 +1,42 @@ +#!/bin/sh +# (christer.edwards@gmail.com) +# initialize a Bastille repo + +if [ $# -lt 1 ] || [ $# -gt 1 ]; then + echo "Usage: bbsd-init-repo /path/to/repo" + return 1 +fi + +REPOPATH=$1 + +RODIRS="root/bin root/boot root/dev root/lib\ + root/libexec root/rescue root/sbin\ + root/usr/bin root/usr/include root/usr/lib\ + root/usr/libdata root/usr/libexec\ + root/usr/sbin root/usr/share root/tmp" + +RWDIRS="root/etc root/root root/usr/local root/var" + +bbsd_init_repo() +{ + local _dir + + for _dir in ${RWDIRS}; do + mkdir -p "${REPOPATH}"/"${_dir}" + done + + for _dir in ${RODIRS}; do + mkdir -p "${REPOPATH}"/"${_dir}" + cat << EOF > "${_dir}"/.gitignore +# Ignore everything in this directory +# All directory contents will be lost +* +# Except this file +!.gitignore +EOF +done + +chmod 1777 root/tmp +} + +bbsd_init_repo diff --git a/usr/local/bin/bbsd-login b/usr/local/bin/bbsd-login new file mode 100755 index 0000000..c0c376f --- /dev/null +++ b/usr/local/bin/bbsd-login @@ -0,0 +1,11 @@ +#!/bin/sh +# +# jexec $1 /usr/bin/login -f root + +if [ $# -eq 1 ]; then + jexec $1 /usr/bin/login -f root +fi + +if [ $# -eq 2 ]; then + jexec $1 /usr/bin/login -f $2 +fi diff --git a/usr/local/bin/bbsd-pkg b/usr/local/bin/bbsd-pkg new file mode 100755 index 0000000..62c8578 --- /dev/null +++ b/usr/local/bin/bbsd-pkg @@ -0,0 +1,31 @@ +#!/bin/sh +# +# execute $2 inside targeted jail(s) + +if [ $# -gt 2 ] || [ $# -lt 2 ]; then + echo "Usage: bbsd-pkg [glob|ALL] 'package command'." + exit 1 +fi + +if [ "$1" = 'ALL' ]; then + JAILS=$(jls -N | awk '!/JID/{print $1}') + echo "Targeting all containers." + echo + for i in ${JAILS}; do + echo "${i}:" + pkg -j "${i}" "$2" + echo + done +fi + +if [ "$1" != 'ALL' ]; then + JAILS=$(jls -N | awk '!/JID/{print $1}' | grep "$1") + echo "Targeting specified containers." + echo "${JAILS}" + echo + for i in ${JAILS}; do + echo "${i}:" + pkg -j "${i}" "$2" + echo + done +fi diff --git a/usr/local/bin/bbsd-restart b/usr/local/bin/bbsd-restart new file mode 100755 index 0000000..81121d2 --- /dev/null +++ b/usr/local/bin/bbsd-restart @@ -0,0 +1,35 @@ +#!/bin/sh +# (christer.edwards@gmail.com) +# restart jail + +if [ $# -lt 1 ]; then + printf "Required: jail name(s)." + exit 1 +fi + +ARGS=$* + +for jail in ${ARGS}; do + PREFIX=/usr/local + PLATFORM=${PREFIX}/bastille + JAIL_BASE=${PLATFORM}/jails/${jail} + + JAIL_ROOT=${JAIL_BASE}/root + JAIL_CONF=${JAIL_BASE}/jail.conf + PKGS_CONF=${JAIL_BASE}/pkgs.conf + JAIL_JID=${JAIL_BASE}/${jail}.jid + + err_msg() { + printf "ERROR:\t$@\n" + } + + if [ ! -d ${JAIL_ROOT} ]; then + err_msg "Jail (${jail}) does not exist(?)." + + [ ! -f ${JAIL_CONF} ] && err_msg "jail.conf not found." + [ ! -f ${PKGS_CONF} ] && err_msg "pkgs.conf not found." + fi + if [ -d ${JAIL_ROOT} ]; then + jail -rc -f "${JAIL_CONF}" ${jail} + fi +done diff --git a/usr/local/bin/bbsd-start b/usr/local/bin/bbsd-start new file mode 100755 index 0000000..a940db4 --- /dev/null +++ b/usr/local/bin/bbsd-start @@ -0,0 +1,35 @@ +#!/bin/sh +# (christer.edwards@gmail.com) +# start jail + +if [ $# -lt 1 ]; then + printf "Required: jail name(s)." + exit 1 +fi + +ARGS=$* + +for jail in ${ARGS}; do + PREFIX=/usr/local + PLATFORM=${PREFIX}/bastille + JAIL_BASE=${PLATFORM}/jails/${jail} + + JAIL_ROOT=${JAIL_BASE}/root + JAIL_CONF=${JAIL_BASE}/jail.conf + PKGS_CONF=${JAIL_BASE}/pkgs.conf + JAIL_JID=${JAIL_BASE}/${jail}.jid + + err_msg() { + printf "ERROR:\t$@\n" + } + + if [ ! -d ${JAIL_ROOT} ]; then + err_msg "Jail (${jail}) does not exist(?)." + elif [ -d ${JAIL_ROOT} ]; then + jail -c -f "${JAIL_CONF}" -J "${JAIL_JID}" ${jail} + pfctl -f /etc/pf.conf + #if [ -s ${PKGS_CONF} ]; then + # pkg -j ${jail} install -y $(cat ${PKGS_CONF}) + #fi + fi +done diff --git a/usr/local/bin/bbsd-stop b/usr/local/bin/bbsd-stop new file mode 100755 index 0000000..b47da52 --- /dev/null +++ b/usr/local/bin/bbsd-stop @@ -0,0 +1,32 @@ +#!/bin/sh +# (christer.edwards@gmail.com) +# stop jail + +if [ $# -lt 1 ]; then + printf "Required: jail name(s)." + exit 1 +fi + +ARGS=$* + +for jail in ${ARGS}; do + PREFIX=/usr/local + PLATFORM=${PREFIX}/bastille + JAIL_BASE=${PLATFORM}/jails/${jail} + + JAIL_ROOT=${JAIL_BASE}/root + JAIL_CONF=${JAIL_BASE}/jail.conf + PKGS_CONF=${JAIL_BASE}/pkgs.conf + JAIL_JID=${JAIL_BASE}/${jail}.jid + + err_msg() { + printf "ERROR:\t$@\n" + } + + if [ ! -d ${JAIL_ROOT} ]; then + err_msg "Jail (${jail}) does not exist(?)." + fi + if [ -d ${JAIL_ROOT} ]; then + jail -r -f ${JAIL_CONF} ${jail} + fi +done diff --git a/usr/local/bin/bbsd-top b/usr/local/bin/bbsd-top new file mode 100755 index 0000000..6e84953 --- /dev/null +++ b/usr/local/bin/bbsd-top @@ -0,0 +1,5 @@ +#!/bin/sh +# +# run top inside a jail + +/usr/bin/top -J $1