mirror of
https://github.com/hackacad/bastille.git
synced 2025-12-21 09:41:47 +01:00
Merge branch 'BastilleBSD:master' into rdr-multiple-interfaces
This commit is contained in:
@@ -28,6 +28,7 @@ Christer Edwards [christer.edwards@gmail.com]
|
||||
- Niketh Murali
|
||||
- Eric Borisch
|
||||
- Kevet Duncombe
|
||||
- Victor Tschetter
|
||||
|
||||
### Special thanks
|
||||
Software doesn't happen in a vacuum. Thank you to the following people who may
|
||||
|
||||
@@ -62,7 +62,7 @@ Available Commands:
|
||||
config Get or set a config value for the targeted container(s).
|
||||
console Console into a running container.
|
||||
convert Convert a Thin container into a Thick container.
|
||||
cp cp(1) files from host to targeted container(s).
|
||||
cp cp(1) files from host or container to host or 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).
|
||||
@@ -70,12 +70,13 @@ Available Commands:
|
||||
help Help about any command.
|
||||
htop Interactive process viewer (requires htop).
|
||||
import Import a specified container.
|
||||
jcp cp(1) files from a jail to jail(s).
|
||||
limits Apply resources limits to targeted container(s). See rctl(8).
|
||||
list List containers (running).
|
||||
mount Mount a volume inside the targeted container(s).
|
||||
pkg Manipulate binary packages within targeted container(s). See pkg(8).
|
||||
rcp cp(1) files from a jail to host.
|
||||
rdr Redirect host port to container port.
|
||||
rcp reverse cp(1) files from a single container to the host.
|
||||
rename Rename a container.
|
||||
restart Restart a running container.
|
||||
service Manage services within targeted container(s).
|
||||
@@ -97,7 +98,7 @@ Use "bastille command -h|--help" for more information about a command.
|
||||
|
||||
```
|
||||
|
||||
## 0.12-beta
|
||||
## 0.13-beta
|
||||
This document outlines the basic usage of the Bastille container management
|
||||
framework. This release is still considered beta.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Bastille is available in the official FreeBSD ports tree at
|
||||
`sysutils/bastille`. Binary packages available in `quarterly` and `latest`
|
||||
repositories.
|
||||
|
||||
Current version is `0.12.20250111`.
|
||||
Current version is `0.13.20250126`.
|
||||
|
||||
To install from the FreeBSD package repository:
|
||||
|
||||
|
||||
32
docs/chapters/subcommands/config.rst
Normal file
32
docs/chapters/subcommands/config.rst
Normal file
@@ -0,0 +1,32 @@
|
||||
=======
|
||||
config
|
||||
=======
|
||||
|
||||
Gets or sets properties for a target container.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
Usage: bastille config TARGET get|set propertyName [newValue]
|
||||
|
||||
Getting a property that *is* defined in jail.conf:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ishmael ~ # bastille config azkaban get ip4.addr
|
||||
192.168.2.23
|
||||
|
||||
Getting a property that *is not* defined in jail.conf
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ishmael ~ # bastille config azkaban get notaproperty
|
||||
not set
|
||||
|
||||
Setting a property:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ishmael ~ # bastille config azkaban set ip4.addr 192.168.2.24
|
||||
A restart is required for the changes to be applied. See 'bastille restart azkaban'.
|
||||
|
||||
The restart message will appear every time a property is set.
|
||||
@@ -2,8 +2,7 @@
|
||||
console
|
||||
=======
|
||||
|
||||
This sub-command launches a login shell into the container. Default is password-less
|
||||
root login.
|
||||
This sub-command launches a login shell into the container. Default is password-less root login.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
@@ -11,6 +10,25 @@ root login.
|
||||
[folsom]:
|
||||
root@folsom:~ #
|
||||
|
||||
TARGET can also be a running jails JID value.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ishmael ~ # bastille list
|
||||
JID IP Address Hostname Path
|
||||
1 10.1.2.3 ishmael /usr/local/bastille/jails/ishmael/root
|
||||
ishmael ~ # bastille console 1
|
||||
[ishmael]:
|
||||
root@ishmael:~ #
|
||||
|
||||
At this point you are logged in to the container and have full shell access. The
|
||||
system is yours to use and/or abuse as you like. Any changes made inside the
|
||||
container are limited to the container.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
"Usage: bastille console [option(s)] TARGET [user]"
|
||||
Options:
|
||||
|
||||
-a | --auto Auto mode. Start/stop jail(s) if required.
|
||||
-x | --debug Enable debug mode.
|
||||
|
||||
@@ -2,21 +2,31 @@
|
||||
cp
|
||||
==
|
||||
|
||||
This command allows efficiently copying files from host to container(s).
|
||||
This command allows copying files from host to jail(s).
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ishmael ~ # bastille cp ALL /tmp/resolv.conf-cf etc/resolv.conf
|
||||
ishmael ~ # bastille cp ALL /tmp/resolv.conf-cf /etc/resolv.conf
|
||||
[bastion]:
|
||||
|
||||
/tmp/resolv.conf-cf -> /usr/local/bastille/jails/bastion/root/etc/resolv.conf
|
||||
[unbound0]:
|
||||
|
||||
/tmp/resolv.conf-cf -> /usr/local/bastille/jails/unbound0/root/etc/resolv.conf
|
||||
[unbound1]:
|
||||
|
||||
/tmp/resolv.conf-cf -> /usr/local/bastille/jails/unbound1/root/etc/resolv.conf
|
||||
[squid]:
|
||||
|
||||
/tmp/resolv.conf-cf -> /usr/local/bastille/jails/squid/root/etc/resolv.conf
|
||||
[nginx]:
|
||||
|
||||
/tmp/resolv.conf-cf -> /usr/local/bastille/jails/nginx/root/etc/resolv.conf
|
||||
[folsom]:
|
||||
/tmp/resolv.conf-cf -> /usr/local/bastille/jails/folsom/root/etc/resolv.conf
|
||||
|
||||
Unless you see errors reported in the output the `cp` was successful.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ishmael ~ # bastille cp help
|
||||
Usage: bastille cp [option(s)] TARGET HOST_PATH JAIL_PATH
|
||||
Options:
|
||||
|
||||
-q | --quiet Suppress output.
|
||||
-x | --debug Enable debug mode.
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
htop
|
||||
====
|
||||
|
||||
This one runs `htop` inside the container.
|
||||
note: won't work if you don't have htop installed in the container.
|
||||
This command runs `htop` in the targeted jail.
|
||||
Requires htop to be installed in the jail.
|
||||
|
||||
|
||||
.. image:: ../../images/htop.png
|
||||
|
||||
30
docs/chapters/subcommands/jcp.rst
Normal file
30
docs/chapters/subcommands/jcp.rst
Normal file
@@ -0,0 +1,30 @@
|
||||
===
|
||||
jcp
|
||||
===
|
||||
|
||||
This command allows copying files from jail to jail(s).
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ishmael ~ # bastille jcp bastion /tmp/resolv.conf-cf ALL /etc/resolv.conf
|
||||
[unbound0]:
|
||||
/usr/local/bastille/jails/bastion/root/tmp/resolv.conf-cf -> /usr/local/bastille/jails/unbound0/root/etc/resolv.conf
|
||||
[unbound1]:
|
||||
/usr/local/bastille/jails/bastion/root/tmp/resolv.conf-cf -> /usr/local/bastille/jails/unbound1/root/etc/resolv.conf
|
||||
[squid]:
|
||||
/usr/local/bastille/jails/bastion/root/tmp/resolv.conf-cf -> /usr/local/bastille/jails/squid/root/etc/resolv.conf
|
||||
[nginx]:
|
||||
/usr/local/bastille/jails/bastion/root/tmp/resolv.conf-cf -> /usr/local/bastille/jails/nginx/root/etc/resolv.conf
|
||||
[folsom]:
|
||||
/usr/local/bastille/jails/bastion/root/tmp/resolv.conf-cf -> /usr/local/bastille/jails/folsom/root/etc/resolv.conf
|
||||
|
||||
Unless you see errors reported in the output the `jcp` was successful.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ishmael ~ # bastille jcp help
|
||||
Usage: bastille jcp [option(s)] SOURCE_JAIL JAIL_PATH DEST_JAIL JAIL_PATH
|
||||
Options:
|
||||
|
||||
-q | --quiet Suppress output.
|
||||
-x | --debug Enable debug mode.
|
||||
@@ -10,7 +10,7 @@ Syntax follows standard `/etc/fstab` format:
|
||||
|
||||
Usage: bastille mount TARGET HOST_PATH JAIL_PATH [filesystem_type options dump pass_number]
|
||||
|
||||
The 'options' string can include a comma-separated list of mount options, but must start with 'ro' or 'rw'.
|
||||
The 'options' string can include a comma-separated list of mount options, but must include one of (rw,ro,rq,sw,xx) according to fstab documentation.
|
||||
|
||||
Example: Mount a tmpfs filesystem with options.
|
||||
.. code-block:: shell
|
||||
|
||||
22
docs/chapters/subcommands/rcp.rst
Normal file
22
docs/chapters/subcommands/rcp.rst
Normal file
@@ -0,0 +1,22 @@
|
||||
===
|
||||
rcp
|
||||
===
|
||||
|
||||
This command allows copying files from jail to host.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ishmael ~ # bastille rcp bastion /test/testfile.txt /tmp/testfile.txt
|
||||
[bastion]:
|
||||
/usr/local/bastille/jails/bastion/root/test/testfile.txt -> /tmp/testfile.txt
|
||||
|
||||
Unless you see errors reported in the output the `rcp` was successful.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ishmael ~ # bastille rcp help
|
||||
Usage: bastille rcp [option(s)] TARGET JAIL_PATH HOST_PATH
|
||||
Options:
|
||||
|
||||
-q | --quiet Suppress output.
|
||||
-x | --debug Enable debug mode.
|
||||
@@ -2,7 +2,7 @@
|
||||
top
|
||||
===
|
||||
|
||||
This one runs `top` in that container.
|
||||
This command runs `top` in the targeted jail.
|
||||
|
||||
|
||||
.. image:: ../../images/top.png
|
||||
|
||||
@@ -12,9 +12,9 @@ copyright = '2018-2025, Christer Edwards'
|
||||
author = 'Christer Edwards'
|
||||
|
||||
# The short X.Y version
|
||||
version = '0.12.20250111'
|
||||
version = '0.13.20250126'
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = '0.12.20250111-beta'
|
||||
release = '0.13.20250126-beta'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
@@ -78,7 +78,7 @@ bastille_perms_check() {
|
||||
bastille_perms_check
|
||||
|
||||
## version
|
||||
BASTILLE_VERSION="0.12.20250111"
|
||||
BASTILLE_VERSION="0.13.20250126"
|
||||
|
||||
usage() {
|
||||
cat << EOF
|
||||
@@ -95,19 +95,21 @@ Available Commands:
|
||||
config Get or set a config value for the targeted container(s).
|
||||
console Console into a running container.
|
||||
convert Convert a Thin container into a Thick container.
|
||||
cp cp(1) files from host to targeted container(s).
|
||||
cp cp(1) files from host to jail(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).
|
||||
etcupdate Update /etc directory to specified release.
|
||||
export Exports a specified container.
|
||||
help Help about any command.
|
||||
htop Interactive process viewer (requires htop).
|
||||
jcp cp(1) files from a jail to jail(s).
|
||||
import Import a specified container.
|
||||
limits Apply resources limits to targeted container(s). See rctl(8).
|
||||
list List containers (running).
|
||||
mount Mount a volume inside the targeted container(s).
|
||||
pkg Manipulate binary packages within targeted container(s). See pkg(8).
|
||||
rcp reverse cp(1) files from a single container to the host.
|
||||
rcp cp(1) files from a jail to host.
|
||||
rdr Redirect host port to container port.
|
||||
rename Rename a container.
|
||||
restart Restart a running container.
|
||||
@@ -137,7 +139,7 @@ EOF
|
||||
CMD=$1
|
||||
shift
|
||||
|
||||
target_all_jails() {
|
||||
target_all_jails_old() {
|
||||
_JAILS=$(/usr/sbin/jls name)
|
||||
JAILS=""
|
||||
for _jail in ${_JAILS}; do
|
||||
@@ -148,7 +150,7 @@ target_all_jails() {
|
||||
done
|
||||
}
|
||||
|
||||
check_target_is_running() {
|
||||
check_target_is_running_old() {
|
||||
if [ ! "$(/usr/sbin/jls name | awk "/^${TARGET}$/")" ]; then
|
||||
error_exit "[${TARGET}]: Not started. See 'bastille start ${TARGET}'."
|
||||
fi
|
||||
@@ -163,10 +165,11 @@ version|-v|--version)
|
||||
help|-h|--help)
|
||||
usage
|
||||
;;
|
||||
bootstrap|create|destroy|export|htop|import|list|mount|rdr|restart|setup|start|top|umount|update|upgrade|verify)
|
||||
|
||||
bootstrap|clone|console|create|cp|destroy|etcupdate|export|htop|import|jcp|list|mount|rcp|rdr|rename|restart|setup|start|top|umount|update|upgrade|verify)
|
||||
# Nothing "extra" to do for these commands. -- cwells
|
||||
;;
|
||||
clone|config|cmd|console|convert|cp|edit|limits|pkg|rcp|rename|service|stop|sysrc|tags|template|zfs)
|
||||
config|cmd|convert|edit|limits|pkg|service|stop|sysrc|tags|template|zfs)
|
||||
# Parse the target and ensure it exists. -- cwells
|
||||
if [ $# -eq 0 ]; then # No target was given, so show the command's help. -- cwells
|
||||
PARAMS='help'
|
||||
@@ -187,15 +190,15 @@ clone|config|cmd|console|convert|cp|edit|limits|pkg|rcp|rename|service|stop|sysr
|
||||
fi
|
||||
|
||||
if [ "${TARGET}" = 'ALL' ]; then
|
||||
target_all_jails
|
||||
target_all_jails_old
|
||||
elif [ "${CMD}" = "pkg" ] && [ "${TARGET}" = '-H' ] || [ "${TARGET}" = '--host' ]; then
|
||||
TARGET="${1}"
|
||||
USE_HOST_PKG=1
|
||||
if [ "${TARGET}" = 'ALL' ]; then
|
||||
target_all_jails
|
||||
target_all_jails_old
|
||||
else
|
||||
JAILS="${TARGET}"
|
||||
check_target_is_running
|
||||
check_target_is_running_old
|
||||
fi
|
||||
shift
|
||||
elif [ "${CMD}" = 'template' ] && [ "${TARGET}" = '--convert' ]; then
|
||||
@@ -211,8 +214,8 @@ clone|config|cmd|console|convert|cp|edit|limits|pkg|rcp|rename|service|stop|sysr
|
||||
fi
|
||||
|
||||
case "${CMD}" in
|
||||
cmd|console|pkg|service|stop|sysrc|template)
|
||||
check_target_is_running
|
||||
cmd|pkg|service|stop|sysrc|template)
|
||||
check_target_is_running_old
|
||||
;;
|
||||
convert|rename)
|
||||
# Require the target to be stopped. -- cwells
|
||||
|
||||
@@ -34,24 +34,78 @@
|
||||
. /usr/local/etc/bastille/bastille.conf
|
||||
|
||||
usage() {
|
||||
error_exit "Usage: bastille clone TARGET NEW_NAME IPADDRESS"
|
||||
error_notify "Usage: bastille clone [option(s)] TARGET NEW_NAME IP_ADDRESS"
|
||||
cat << EOF
|
||||
Options:
|
||||
|
||||
-a | --auto Auto mode. Start/stop jail(s) if required. Cannot be used with [-l|--live].
|
||||
-l | --live Clone a running jail. ZFS only. Jail must be running. Cannot be used with [-a|--auto].
|
||||
-x | --debug Enable debug mode.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Handle special-case commands first
|
||||
case "$1" in
|
||||
help|-h|--help)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
# Handle options.
|
||||
AUTO=0
|
||||
LIVE=0
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|--help|help)
|
||||
usage
|
||||
;;
|
||||
-a|--auto)
|
||||
AUTO=1
|
||||
shift
|
||||
;;
|
||||
-l|--live)
|
||||
if ! checkyesno bastille_zfs_enable; then
|
||||
error_exit "[-l|--live] can only be used with ZFS."
|
||||
else
|
||||
LIVE=1
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
-x|--debug)
|
||||
enable_debug
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do
|
||||
case ${_opt} in
|
||||
a) AUTO=1 ;;
|
||||
l) LIVE=1 ;;
|
||||
x) enable_debug ;;
|
||||
*) error_exit "Unknown Option: \"${1}\""
|
||||
esac
|
||||
done
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -ne 2 ]; then
|
||||
if [ "${AUTO}" -eq 1 ] && [ "${LIVE}" -eq 1 ]; then
|
||||
error_exit "[-a|--auto] cannot be used with [-l|--live]"
|
||||
fi
|
||||
|
||||
if [ $# -ne 3 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
bastille_root_check
|
||||
TARGET="${1}"
|
||||
NEWNAME="${2}"
|
||||
IP="${3}"
|
||||
|
||||
NEWNAME="${1}"
|
||||
IP="${2}"
|
||||
bastille_root_check
|
||||
set_target_single "${TARGET}"
|
||||
|
||||
## don't allow for dots(.) in container names
|
||||
if echo "${NEWNAME}" | grep -q "[.]"; then
|
||||
error_exit "Container names may not contain a dot(.)!"
|
||||
fi
|
||||
|
||||
validate_ip() {
|
||||
IPX_ADDR="ip4.addr"
|
||||
@@ -89,79 +143,153 @@ update_jailconf() {
|
||||
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|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}"
|
||||
sed -i '' "s|${IPX_ADDR} = .*;|${IPX_ADDR} = ${IP};|" "${JAIL_CONFIG}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if grep -qw "vnet;" "${JAIL_CONFIG}"; then
|
||||
update_jailconf_vnet
|
||||
else
|
||||
_ip4="$(bastille config ${TARGET} get ip4.addr | sed 's/,/ /g')"
|
||||
_ip6="$(bastille config ${TARGET} get ip6.addr | sed 's/,/ /g')"
|
||||
# IP4
|
||||
if [ "${_ip4}" != "not set" ]; then
|
||||
for _ip in ${_ip4}; do
|
||||
_ip="$(echo ${_ip} | awk -F"|" '{print $2}')"
|
||||
sed -i '' "/${IPX_ADDR} = .*/ s/${_ip}/${IP}/" "${JAIL_CONFIG}"
|
||||
sed -i '' "/${IPX_ADDR} += .*/ s/${_ip}/127.0.0.1/" "${JAIL_CONFIG}"
|
||||
done
|
||||
fi
|
||||
# IP6
|
||||
if [ "${_ip6}" != "not set" ]; then
|
||||
for _ip in ${_ip6}; do
|
||||
_ip="$(echo ${_ip} | awk -F"|" '{print $2}')"
|
||||
sed -i '' "/${IPX_ADDR} = .*/ s/${_ip}/${IP}/" "${JAIL_CONFIG}"
|
||||
sed -i '' "/${IPX_ADDR} += .*/ s/${_ip}/127.0.0.1/" "${JAIL_CONFIG}"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
update_jailconf_vnet() {
|
||||
bastille_jail_rc_conf="${bastille_jailsdir}/${NEWNAME}/root/etc/rc.conf"
|
||||
|
||||
# Determine number of containers and define an 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
|
||||
if ! grep -q "epair${_num}" "${bastille_jailsdir}"/*/jail.conf; then
|
||||
local uniq_epair="bastille${_num}"
|
||||
local uniq_epair_bridge="${_num}"
|
||||
# since we don't have access to the external_interface variable, we cat the jail.conf file to retrieve the mac prefix
|
||||
# we also do not use the main generate_static_mac function here
|
||||
local macaddr_prefix="$(cat ${JAIL_CONFIG} | grep -m 1 ether | grep -oE '([0-9a-f]{2}(:[0-9a-f]{2}){5})' | awk -F: '{print $1":"$2":"$3}')"
|
||||
local macaddr_suffix="$(echo -n ${NEWNAME} | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')"
|
||||
local macaddr="${macaddr_prefix}:${macaddr_suffix}"
|
||||
# Update the exec.* with uniq_epair when cloning jails.
|
||||
# for VNET jails
|
||||
sed -i '' "s|bastille\([0-9]\{1,\}\)|${uniq_epair}|g" "${JAIL_CONFIG}"
|
||||
sed -i '' "s|e\([0-9]\{1,\}\)a_${NEWNAME}|e${uniq_epair_bridge}a_${NEWNAME}|g" "${JAIL_CONFIG}"
|
||||
sed -i '' "s|e\([0-9]\{1,\}\)b_${NEWNAME}|e${uniq_epair_bridge}b_${NEWNAME}|g" "${JAIL_CONFIG}"
|
||||
sed -i '' "s|epair\([0-9]\{1,\}\)|epair${uniq_epair_bridge}|g" "${JAIL_CONFIG}"
|
||||
sed -i '' "s|exec.prestart += \"ifconfig e0a_bastille\([0-9]\{1,\}\).*description.*|exec.prestart += \"ifconfig e0a_${uniq_epair} description \\\\\"vnet host interface for Bastille jail ${NEWNAME}\\\\\"\";|" "${JAIL_CONFIG}"
|
||||
sed -i '' "s|ether.*:.*:.*:.*:.*:.*a\";|ether ${macaddr}a\";|" "${JAIL_CONFIG}"
|
||||
sed -i '' "s|ether.*:.*:.*:.*:.*:.*b\";|ether ${macaddr}b\";|" "${JAIL_CONFIG}"
|
||||
local _jail_conf="${bastille_jailsdir}/${NEWNAME}/jail.conf"
|
||||
local _rc_conf="${bastille_jailsdir}/${NEWNAME}/root/etc/rc.conf"
|
||||
# Determine number of interfaces and define a uniq_epair
|
||||
local _if_list="$(grep -Eo 'epair[0-9]+|bastille[0-9]+' ${_jail_conf} | sort -u)"
|
||||
for _if in ${_if_list}; do
|
||||
local _epair_if_count="$( (grep -Eo 'epair[0-9]+' ${bastille_jailsdir}/*/jail.conf; ifconfig | grep -Eo '(e[0-9]+a|epair[0-9]+a)' ) | sort -u | wc -l | awk '{print $1}')"
|
||||
local _bastille_if_count="$(grep -Eo 'bastille[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')"
|
||||
local epair_num_range=$((_epair_if_count + 1))
|
||||
local bastille_num_range=$((_bastille_if_count + 1))
|
||||
if echo ${_if} | grep -Eoq 'epair[0-9]+'; then
|
||||
# Update bridged VNET config
|
||||
for _num in $(seq 0 "${epair_num_range}"); do
|
||||
if ! grep -Eoq "epair${_num}" ${bastille_jailsdir}/*/jail.conf && ! ifconfig | grep -Eoq "(e${_num}a|epair${_num}a)"; then
|
||||
# Generate new epair name
|
||||
if [ "$(echo -n "e${_num}a_${NEWNAME}" | awk '{print length}')" -lt 16 ]; then
|
||||
local _new_host_epair="e${_num}a_${NEWNAME}"
|
||||
local _new_jail_epair="e${_num}b_${NEWNAME}"
|
||||
else
|
||||
local _new_host_epair="epair${_num}a"
|
||||
local _new_jail_epair="epair${_num}b"
|
||||
fi
|
||||
# Get epair name from TARGET
|
||||
if grep -Eoq "e[0-9]+a_${TARGET}" "${_jail_conf}"; then
|
||||
_target_host_epair="$(grep -Eo -m 1 "e[0-9]+a_${TARGET}" "${_jail_conf}")"
|
||||
_target_jail_epair="$(grep -Eo -m 1 "e[0-9]+b_${TARGET}" "${_jail_conf}")"
|
||||
else
|
||||
_target_host_epair="${_if}a"
|
||||
_target_jail_epair="${_if}b"
|
||||
fi
|
||||
# Replace host epair name in jail.conf
|
||||
sed -i '' "s|up name ${_target_host_epair}|up name ${_new_host_epair}|g" "${_jail_conf}"
|
||||
sed -i '' "s|${_target_host_epair} ether|${_new_host_epair} ether|g" "${_jail_conf}"
|
||||
sed -i '' "s|deletem ${_target_host_epair}|deletem ${_new_host_epair}|g" "${_jail_conf}"
|
||||
sed -i '' "s|${_target_host_epair} destroy|${_new_host_epair} destroy|g" "${_jail_conf}"
|
||||
sed -i '' "s|${_target_host_epair} description|${_new_host_epair} description|g" "${_jail_conf}"
|
||||
# Replace jail epair name in jail.conf
|
||||
sed -i '' "s|= ${_target_jail_epair};|= ${_new_jail_epair};|g" "${_jail_conf}"
|
||||
sed -i '' "s|up name ${_target_jail_epair}|up name ${_new_jail_epair}|g" "${_jail_conf}"
|
||||
sed -i '' "s|${_target_jail_epair} ether|${_new_jail_epair} ether|g" "${_jail_conf}"
|
||||
# Replace epair name in jail.conf
|
||||
sed -i '' "s|${_if}|epair${_num}|g" "${_jail_conf}"
|
||||
# If jail had a static MAC, generate one for clone
|
||||
if grep -q ether ${_jail_conf}; then
|
||||
local external_interface="$(grep "epair${_num}a" ${_jail_conf} | grep -o '[^ ]* addm' | awk '{print $1}')"
|
||||
generate_static_mac "${NEWNAME}" "${external_interface}"
|
||||
sed -i '' "s|${_new_host_epair} ether.*:.*:.*:.*:.*:.*a\";|${_new_host_epair} ether ${macaddr}a\";|" "${_jail_conf}"
|
||||
sed -i '' "s|${_new_jail_epair} ether.*:.*:.*:.*:.*:.*b\";|${_new_jail_epair} ether ${macaddr}b\";|" "${_jail_conf}"
|
||||
fi
|
||||
# Replace epair description
|
||||
sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${_jail_conf}"
|
||||
# Update /etc/rc.conf
|
||||
local _jail_vnet="$(grep ${_target_jail_epair} "${_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")"
|
||||
sed -i '' "s|${_target_jail_epair}_name|${_new_jail_epair}_name|" "${_rc_conf}"
|
||||
if grep "vnet0" "${_rc_conf}" | grep -q "${_new_jail_epair}_name"; then
|
||||
if [ "${IP}" = "0.0.0.0" ]; then
|
||||
sysrc -f "${_rc_conf}" ifconfig_vnet0="SYNCDHCP"
|
||||
else
|
||||
sysrc -f "${_rc_conf}" ifconfig_vnet0="inet ${IP}"
|
||||
fi
|
||||
else
|
||||
sysrc -f "${_rc_conf}" ifconfig_${_jail_vnet}="SYNCDHCP"
|
||||
fi
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
elif echo ${_if} | grep -Eoq 'bastille[0-9]+'; then
|
||||
# Update VNET config
|
||||
for _num in $(seq 0 "${bastille_num_range}"); do
|
||||
if ! grep -oq "bastille${_num}" ${bastille_jailsdir}/*/jail.conf; then
|
||||
# Update jail.conf epair name
|
||||
local uniq_epair="bastille${_num}"
|
||||
local _if_vnet="$(grep ${_if} "${_rc_conf}" | grep -Eo -m 1 "vnet[0-9]+")"
|
||||
sed -i '' "s|${_if}|${uniq_epair}|g" "${_jail_conf}"
|
||||
# If jail had a static MAC, generate one for clone
|
||||
if grep ether ${_jail_conf} | grep -qoc ${uniq_epair}; then
|
||||
local external_interface="$(grep ${uniq_epair} ${_jail_conf} | grep -o 'addm.*' | awk '{print $3}' | sed 's/["|;]//g')"
|
||||
generate_static_mac "${NEWNAME}" "${external_interface}"
|
||||
sed -i '' "s|${uniq_epair} ether.*:.*:.*:.*:.*:.*a\";|${uniq_epair} ether ${macaddr}a\";|" "${_jail_conf}"
|
||||
sed -i '' "s|${uniq_epair} ether.*:.*:.*:.*:.*:.*b\";|${uniq_epair} ether ${macaddr}b\";|" "${_jail_conf}"
|
||||
fi
|
||||
sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${_jail_conf}"
|
||||
# Update /etc/rc.conf
|
||||
sed -i '' "s|ifconfig_e0b_${_if}_name|ifconfig_e0b_${uniq_epair}_name|" "${_rc_conf}"
|
||||
if grep "vnet0" "${_rc_conf}" | grep -q ${uniq_epair}; then
|
||||
if [ "${IP}" = "0.0.0.0" ]; then
|
||||
sysrc -f "${_rc_conf}" ifconfig_vnet0="SYNCDHCP"
|
||||
else
|
||||
sysrc -f "${_rc_conf}" ifconfig_vnet0=" inet ${IP} "
|
||||
fi
|
||||
else
|
||||
sysrc -f "${_rc_conf}" ifconfig_${_if_vnet}="SYNCDHCP"
|
||||
fi
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
# Rename interface to new uniq_epair
|
||||
sed -i '' "s|ifconfig_e0b_bastille.*_name|ifconfig_e0b_${uniq_epair}_name|" "${bastille_jail_rc_conf}"
|
||||
sed -i '' "s|ifconfig_e.*b_${TARGET}_name|ifconfig_e${uniq_epair_bridge}b_${NEWNAME}_name|" "${bastille_jail_rc_conf}"
|
||||
|
||||
# If 0.0.0.0 set DHCP, else set static IP address
|
||||
if [ "${IP}" = "0.0.0.0" ]; then
|
||||
sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="SYNCDHCP"
|
||||
else
|
||||
sysrc -f "${bastille_jail_rc_conf}" ifconfig_vnet0="inet ${IP}"
|
||||
fi
|
||||
}
|
||||
|
||||
update_fstab() {
|
||||
# Update fstab to use the new name
|
||||
FSTAB_CONFIG="${bastille_jailsdir}/${NEWNAME}/fstab"
|
||||
if [ -f "${FSTAB_CONFIG}" ]; then
|
||||
# Update additional fstab paths with new jail path
|
||||
sed -i '' "s|${bastille_jailsdir}/${TARGET}/root/|${bastille_jailsdir}/${NEWNAME}/root/|" "${FSTAB_CONFIG}"
|
||||
fi
|
||||
}
|
||||
|
||||
clone_jail() {
|
||||
# Attempt container clone
|
||||
info "Attempting to clone '${TARGET}' to ${NEWNAME}..."
|
||||
|
||||
info "Attempting to clone ${TARGET} to ${NEWNAME}..."
|
||||
|
||||
if ! [ -d "${bastille_jailsdir}/${NEWNAME}" ]; then
|
||||
if checkyesno bastille_zfs_enable; then
|
||||
if [ "${LIVE}" -eq 1 ]; then
|
||||
check_target_is_running "${TARGET}" || error_exit "[-l|--live] can only be used with a running jail."
|
||||
else check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then
|
||||
bastille stop "${TARGET}"
|
||||
else
|
||||
error_notify "Jail is running."
|
||||
error_exit "Use [-a|--auto] to force stop the jail, or [-l|--live] (ZFS only) to clone a running jail."
|
||||
fi
|
||||
fi
|
||||
if [ -n "${bastille_zfs_zpool}" ]; then
|
||||
# Replicate the existing container
|
||||
DATE=$(date +%F-%H%M%S)
|
||||
@@ -177,13 +305,13 @@ clone_jail() {
|
||||
zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NEWNAME}@bastille_clone_${DATE}"
|
||||
fi
|
||||
else
|
||||
# Just clone the jail directory
|
||||
# Check if container is running
|
||||
if [ -n "$(/usr/sbin/jls name | awk "/^${TARGET}$/")" ]; then
|
||||
error_exit "${TARGET} is running. See 'bastille stop ${TARGET}'."
|
||||
# Perform container file copy (archive mode)
|
||||
check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then
|
||||
bastille stop "${TARGET}"
|
||||
else
|
||||
error_notify "Jail is running."
|
||||
error_exit "Use [-a|--auto] to force stop the jail."
|
||||
fi
|
||||
|
||||
# Perform container file copy(archive mode)
|
||||
cp -a "${bastille_jailsdir}/${TARGET}" "${bastille_jailsdir}/${NEWNAME}"
|
||||
fi
|
||||
else
|
||||
@@ -192,7 +320,7 @@ clone_jail() {
|
||||
|
||||
# Generate jail configuration files
|
||||
update_jailconf
|
||||
update_fstab
|
||||
update_fstab "${TARGET}" "${NEWNAME}"
|
||||
|
||||
# Display the exist status
|
||||
if [ "$?" -ne 0 ]; then
|
||||
@@ -200,14 +328,12 @@ clone_jail() {
|
||||
else
|
||||
info "Cloned '${TARGET}' to '${NEWNAME}' successfully."
|
||||
fi
|
||||
if [ "${AUTO}" -eq 1 ] || [ "${LIVE}" -eq 1 ]; then
|
||||
bastille start "${NEWNAME}"
|
||||
fi
|
||||
}
|
||||
|
||||
## don't allow for dots(.) in container names
|
||||
if echo "${NEWNAME}" | grep -q "[.]"; then
|
||||
error_exit "Container names may not contain a dot(.)!"
|
||||
fi
|
||||
|
||||
## check if ip address is valid
|
||||
# Check if IP address is valid.
|
||||
if [ -n "${IP}" ]; then
|
||||
validate_ip
|
||||
else
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# Source config file
|
||||
. /usr/local/etc/bastille/bastille.conf
|
||||
if [ -f /usr/local/etc/bastille/bastille.conf ]; then
|
||||
. /usr/local/etc/bastille/bastille.conf
|
||||
fi
|
||||
|
||||
COLOR_RED=
|
||||
COLOR_GREEN=
|
||||
@@ -50,24 +52,30 @@ enable_color() {
|
||||
. /usr/local/share/bastille/colors.pre.sh
|
||||
}
|
||||
|
||||
enable_debug() {
|
||||
# Enable debug mode.
|
||||
warn "***DEBUG MODE***"
|
||||
set -x
|
||||
}
|
||||
|
||||
# If "NO_COLOR" environment variable is present, or we aren't speaking to a
|
||||
# tty, disable output colors.
|
||||
if [ -z "${NO_COLOR}" ] && [ -t 1 ]; then
|
||||
enable_color
|
||||
fi
|
||||
|
||||
# Error/Info functions
|
||||
error_notify() {
|
||||
echo -e "${COLOR_RED}$*${COLOR_RESET}" 1>&2
|
||||
}
|
||||
|
||||
# Notify message on error, and continue to next jail
|
||||
error_continue() {
|
||||
error_notify "$@"
|
||||
# Disabling this shellcheck as we only ever call it inside of a loop
|
||||
# shellcheck disable=SC2104
|
||||
continue
|
||||
}
|
||||
|
||||
# Notify message on error, but do not exit
|
||||
error_notify() {
|
||||
echo -e "${COLOR_RED}$*${COLOR_RESET}" 1>&2
|
||||
}
|
||||
|
||||
# Notify message on error and exit
|
||||
error_exit() {
|
||||
error_notify "$@"
|
||||
@@ -84,7 +92,8 @@ warn() {
|
||||
|
||||
check_target_exists() {
|
||||
local _TARGET="${1}"
|
||||
if [ ! -d "${bastille_jailsdir}"/"${_TARGET}" ]; then
|
||||
local _jaillist="$(bastille list jails)"
|
||||
if ! echo "${_jaillist}" | grep -Eq "^${_TARGET}$"; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
@@ -93,7 +102,7 @@ check_target_exists() {
|
||||
|
||||
check_target_is_running() {
|
||||
local _TARGET="${1}"
|
||||
if [ ! "$(/usr/sbin/jls name | awk "/^${_TARGET}$/")" ]; then
|
||||
if ! jls name | grep -Eq "^${_TARGET}$"; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
@@ -102,89 +111,67 @@ check_target_is_running() {
|
||||
|
||||
check_target_is_stopped() {
|
||||
local _TARGET="${1}"
|
||||
if [ "$(/usr/sbin/jls name | awk "/^${_TARGET}$/")" ]; then
|
||||
if jls name | grep -Eq "^${_TARGET}$"; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
generate_static_mac() {
|
||||
local jail_name="${1}"
|
||||
local external_interface="${2}"
|
||||
local external_interface_mac="$(ifconfig ${external_interface} | grep ether | awk '{print $2}' | sed 's#:##g')"
|
||||
local macaddr_prefix="$(echo -n "${external_interface_mac}" | sha256 | cut -b -6 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')"
|
||||
local macaddr_suffix="$(echo -n "${jail_name}" | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')"
|
||||
if [ -z "${macaddr_prefix}" ] || [ -z "${macaddr_suffix}" ]; then
|
||||
error_notify "Failed to generate MAC address."
|
||||
get_jail_name() {
|
||||
local _JID="${1}"
|
||||
local _jailname="$(jls -j ${_JID} name 2>/dev/null)"
|
||||
if [ -z "${_jailname}" ]; then
|
||||
return 1
|
||||
else
|
||||
echo "${_jailname}"
|
||||
fi
|
||||
macaddr="${macaddr_prefix}:${macaddr_suffix}"
|
||||
export macaddr
|
||||
}
|
||||
|
||||
generate_vnet_jail_netblock() {
|
||||
local jail_name="$1"
|
||||
local use_unique_bridge="$2"
|
||||
local external_interface="$3"
|
||||
generate_static_mac "${jail_name}" "${external_interface}"
|
||||
## determine number of containers + 1
|
||||
## iterate num and grep all jail configs
|
||||
## define uniq_epair
|
||||
local jail_list="$(bastille list jails)"
|
||||
if [ -n "${jail_list}" ]; then
|
||||
local list_jails_num="$(echo "${jail_list}" | wc -l | awk '{print $1}')"
|
||||
local num_range=$((list_jails_num + 1))
|
||||
for _num in $(seq 0 "${num_range}"); do
|
||||
if ! grep -q "e[0-9]b_bastille${_num}" "${bastille_jailsdir}"/*/jail.conf; then
|
||||
if ! grep -q "epair${_num}" "${bastille_jailsdir}"/*/jail.conf; then
|
||||
local uniq_epair="bastille${_num}"
|
||||
local uniq_epair_bridge="${_num}"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
jail_autocomplete() {
|
||||
local _TARGET="${1}"
|
||||
local _jaillist="$(bastille list jails)"
|
||||
local _AUTOTARGET="$(echo "${_jaillist}" | grep -E "^${_TARGET}")"
|
||||
if [ -n "${_AUTOTARGET}" ]; then
|
||||
if [ "$(echo "${_AUTOTARGET}" | wc -l)" -eq 1 ]; then
|
||||
echo "${_AUTOTARGET}"
|
||||
else
|
||||
error_continue "Multiple jails found for ${_TARGET}:\n${_AUTOTARGET}"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
local uniq_epair="bastille0"
|
||||
local uniq_epair_bridge="0"
|
||||
fi
|
||||
if [ -n "${use_unique_bridge}" ]; then
|
||||
## generate bridge config
|
||||
cat <<-EOF
|
||||
vnet;
|
||||
vnet.interface = e${uniq_epair_bridge}b_${jail_name};
|
||||
exec.prestart += "ifconfig epair${uniq_epair_bridge} create";
|
||||
exec.prestart += "ifconfig ${external_interface} addm epair${uniq_epair_bridge}a";
|
||||
exec.prestart += "ifconfig epair${uniq_epair_bridge}a up name e${uniq_epair_bridge}a_${jail_name}";
|
||||
exec.prestart += "ifconfig epair${uniq_epair_bridge}b up name e${uniq_epair_bridge}b_${jail_name}";
|
||||
exec.prestart += "ifconfig e${uniq_epair_bridge}a_${jail_name} ether ${macaddr}a";
|
||||
exec.prestart += "ifconfig e${uniq_epair_bridge}b_${jail_name} ether ${macaddr}b";
|
||||
exec.poststop += "ifconfig ${external_interface} deletem e${uniq_epair_bridge}a_${jail_name}";
|
||||
exec.poststop += "ifconfig e${uniq_epair_bridge}a_${jail_name} destroy";
|
||||
EOF
|
||||
else
|
||||
## generate config
|
||||
cat <<-EOF
|
||||
vnet;
|
||||
vnet.interface = e0b_${uniq_epair};
|
||||
exec.prestart += "jib addm ${uniq_epair} ${external_interface}";
|
||||
exec.prestart += "ifconfig e0a_${uniq_epair} ether ${macaddr}a";
|
||||
exec.prestart += "ifconfig e0b_${uniq_epair} ether ${macaddr}b";
|
||||
exec.prestart += "ifconfig e0a_${uniq_epair} description \"vnet host interface for Bastille jail ${jail_name}\"";
|
||||
exec.poststop += "jib destroy ${uniq_epair}";
|
||||
EOF
|
||||
return 2
|
||||
fi
|
||||
}
|
||||
|
||||
set_target() {
|
||||
local _TARGET="${1}"
|
||||
local _TARGET=${1}
|
||||
JAILS=""
|
||||
TARGET=""
|
||||
if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then
|
||||
target_all_jails
|
||||
else
|
||||
check_target_exists "${_TARGET}" || error_exit "Jail not found \"${_TARGET}\""
|
||||
JAILS="${_TARGET}"
|
||||
TARGET="${_TARGET}"
|
||||
export JAILS
|
||||
for _jail in ${_TARGET}; do
|
||||
if [ ! -d "${bastille_jailsdir}/${_TARGET}" ] && echo "${_jail}" | grep -Eq '^[0-9]+$'; then
|
||||
if get_jail_name "${_jail}" > /dev/null; then
|
||||
_jail="$(get_jail_name ${_jail})"
|
||||
else
|
||||
error_continue "Error: JID \"${_jail}\" not found. Is jail running?"
|
||||
fi
|
||||
elif ! check_target_exists "${_jail}"; then
|
||||
if jail_autocomplete "${_jail}" > /dev/null; then
|
||||
_jail="$(jail_autocomplete ${_jail})"
|
||||
elif [ $? -eq 2 ]; then
|
||||
error_continue "Jail not found \"${_jail}\""
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
TARGET="${TARGET} ${_jail}"
|
||||
JAILS="${JAILS} ${_jail}"
|
||||
done
|
||||
export TARGET
|
||||
export JAILS
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -192,13 +179,27 @@ set_target_single() {
|
||||
local _TARGET="${1}"
|
||||
if [ "${_TARGET}" = ALL ] || [ "${_TARGET}" = all ]; then
|
||||
error_exit "[all|ALL] not supported with this command."
|
||||
else
|
||||
check_target_exists "${_TARGET}" || error_exit "Jail not found \"${_TARGET}\""
|
||||
JAILS="${_TARGET}"
|
||||
TARGET="${_TARGET}"
|
||||
export JAILS
|
||||
export TARGET
|
||||
elif [ "$(echo ${_TARGET} | wc -w)" -gt 1 ]; then
|
||||
error_exit "Error: Command only supports a single TARGET."
|
||||
elif [ ! -d "${bastille_jailsdir}/${_TARGET}" ] && echo "${_TARGET}" | grep -Eq '^[0-9]+$'; then
|
||||
if get_jail_name "${_TARGET}" > /dev/null; then
|
||||
_TARGET="$(get_jail_name ${_TARGET})"
|
||||
else
|
||||
error_exit "Error: JID \"${_TARGET}\" not found. Is jail running?"
|
||||
fi
|
||||
elif ! check_target_exists "${_TARGET}"; then
|
||||
if jail_autocomplete "${_TARGET}" > /dev/null; then
|
||||
_TARGET="$(jail_autocomplete ${_TARGET})"
|
||||
elif [ $? -eq 2 ]; then
|
||||
error_exit "Jail not found \"${_TARGET}\""
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
TARGET="${_TARGET}"
|
||||
JAILS="${_TARGET}"
|
||||
export TARGET
|
||||
export JAILS
|
||||
}
|
||||
|
||||
target_all_jails() {
|
||||
@@ -212,6 +213,139 @@ target_all_jails() {
|
||||
export JAILS
|
||||
}
|
||||
|
||||
update_fstab() {
|
||||
local _oldname="${1}"
|
||||
local _newname="${2}"
|
||||
local _fstab="${bastille_jailsdir}/${_newname}/fstab"
|
||||
if [ -f "${_fstab}" ]; then
|
||||
sed -i '' "s|${bastille_jailsdir}/${_oldname}/root/|${bastille_jailsdir}/${_newname}/root/|" "${_fstab}"
|
||||
else
|
||||
error_notify "Error: Failed to update fstab: ${_newmane}"
|
||||
fi
|
||||
}
|
||||
|
||||
generate_static_mac() {
|
||||
local jail_name="${1}"
|
||||
local external_interface="${2}"
|
||||
local external_interface_mac="$(ifconfig ${external_interface} | grep ether | awk '{print $2}')"
|
||||
# Use FreeBSD vendor MAC prefix (58:9c:fc) for jail MAC prefix
|
||||
local macaddr_prefix="58:9c:fc"
|
||||
# Use hash of interface+jailname for jail MAC suffix
|
||||
local macaddr_suffix="$(echo -n "${external_interface_mac}${jail_name}" | sed 's#:##g' | sha256 | cut -b -5 | sed 's/\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F][0-9a-fA-F]\)\([0-9a-fA-F]\)/\1:\2:\3/')"
|
||||
if [ -z "${macaddr_prefix}" ] || [ -z "${macaddr_suffix}" ]; then
|
||||
error_notify "Failed to generate MAC address."
|
||||
fi
|
||||
macaddr="${macaddr_prefix}:${macaddr_suffix}"
|
||||
export macaddr
|
||||
}
|
||||
|
||||
generate_vnet_jail_netblock() {
|
||||
local jail_name="${1}"
|
||||
local use_unique_bridge="${2}"
|
||||
local external_interface="${3}"
|
||||
local static_mac="${4}"
|
||||
## determine number of interfaces + 1
|
||||
## iterate num and grep all jail configs
|
||||
## define uniq_epair
|
||||
local _epair_if_count="$( (grep -Eos 'epair[0-9]+' ${bastille_jailsdir}/*/jail.conf; ifconfig | grep -Eo '(e[0-9]+a|epair[0-9]+a)' ) | sort -u | wc -l | awk '{print $1}')"
|
||||
local _bastille_if_count="$(grep -Eos 'bastille[0-9]+' ${bastille_jailsdir}/*/jail.conf | sort -u | wc -l | awk '{print $1}')"
|
||||
local epair_num_range=$((_epair_if_count + 1))
|
||||
local bastille_num_range=$((_bastille_if_count + 1))
|
||||
if [ -n "${use_unique_bridge}" ]; then
|
||||
if [ "${_epair_if_count}" -gt 0 ]; then
|
||||
for _num in $(seq 0 "${epair_num_range}"); do
|
||||
if ! grep -Eosq "epair${_num}" ${bastille_jailsdir}/*/jail.conf && ! ifconfig | grep -Eosq "(e${_num}a|epair${_num}a)"; then
|
||||
if [ "$(echo -n "e${_num}a_${jail_name}" | awk '{print length}')" -lt 16 ]; then
|
||||
local host_epair=e${_num}a_${jail_name}
|
||||
local jail_epair=e${_num}b_${jail_name}
|
||||
else
|
||||
local host_epair=epair${_num}a
|
||||
local jail_epair=epair${_num}b
|
||||
fi
|
||||
break
|
||||
fi
|
||||
done
|
||||
else
|
||||
if [ "$(echo -n "e0a_${jail_name}" | awk '{print length}')" -lt 16 ]; then
|
||||
local _num=0
|
||||
local host_epair=e${_num}a_${jail_name}
|
||||
local jail_epair=e${_num}b_${jail_name}
|
||||
else
|
||||
local _num=0
|
||||
local host_epair=epair${_num}a
|
||||
local jail_epair=epair${_num}b
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if [ "${_bastille_if_count}" -gt 0 ]; then
|
||||
for _num in $(seq 0 "${bastille_num_range}"); do
|
||||
if ! grep -Eosq "bastille${_num}" ${bastille_jailsdir}/*/jail.conf; then
|
||||
local uniq_epair="bastille${_num}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
else
|
||||
local uniq_epair="bastille0"
|
||||
fi
|
||||
fi
|
||||
## If BRIDGE is enabled, generate bridge config, else generate VNET config
|
||||
if [ -n "${use_unique_bridge}" ]; then
|
||||
if [ -n "${static_mac}" ]; then
|
||||
## Generate bridged VNET config with static MAC address
|
||||
generate_static_mac "${jail_name}" "${external_interface}"
|
||||
cat <<-EOF
|
||||
vnet;
|
||||
vnet.interface = ${jail_epair};
|
||||
exec.prestart += "ifconfig epair${_num} create";
|
||||
exec.prestart += "ifconfig ${external_interface} addm epair${_num}a";
|
||||
exec.prestart += "ifconfig epair${_num}a up name ${host_epair}";
|
||||
exec.prestart += "ifconfig epair${_num}b up name ${jail_epair}";
|
||||
exec.prestart += "ifconfig ${host_epair} ether ${macaddr}a";
|
||||
exec.prestart += "ifconfig ${jail_epair} ether ${macaddr}b";
|
||||
exec.prestart += "ifconfig ${host_epair} description \"vnet host interface for Bastille jail ${jail_name}\"";
|
||||
exec.poststop += "ifconfig ${external_interface} deletem ${host_epair}";
|
||||
exec.poststop += "ifconfig ${host_epair} destroy";
|
||||
EOF
|
||||
else
|
||||
## Generate bridged VNET config without static MAC address
|
||||
cat <<-EOF
|
||||
vnet;
|
||||
vnet.interface = ${jail_epair};
|
||||
exec.prestart += "ifconfig epair${_num} create";
|
||||
exec.prestart += "ifconfig ${external_interface} addm epair${_num}a";
|
||||
exec.prestart += "ifconfig epair${_num}a up name ${host_epair}";
|
||||
exec.prestart += "ifconfig epair${_num}b up name ${jail_epair}";
|
||||
exec.prestart += "ifconfig ${host_epair} description \"vnet host interface for Bastille jail ${jail_name}\"";
|
||||
exec.poststop += "ifconfig ${external_interface} deletem ${host_epair}";
|
||||
exec.poststop += "ifconfig ${host_epair} destroy";
|
||||
EOF
|
||||
fi
|
||||
else
|
||||
if [ -n "${static_mac}" ]; then
|
||||
## Generate VNET config with static MAC address
|
||||
generate_static_mac "${jail_name}" "${external_interface}"
|
||||
cat <<-EOF
|
||||
vnet;
|
||||
vnet.interface = e0b_${uniq_epair};
|
||||
exec.prestart += "jib addm ${uniq_epair} ${external_interface}";
|
||||
exec.prestart += "ifconfig e0a_${uniq_epair} ether ${macaddr}a";
|
||||
exec.prestart += "ifconfig e0b_${uniq_epair} ether ${macaddr}b";
|
||||
exec.prestart += "ifconfig e0a_${uniq_epair} description \"vnet host interface for Bastille jail ${jail_name}\"";
|
||||
exec.poststop += "jib destroy ${uniq_epair}";
|
||||
EOF
|
||||
else
|
||||
## Generate VNET config without static MAC address
|
||||
cat <<-EOF
|
||||
vnet;
|
||||
vnet.interface = e0b_${uniq_epair};
|
||||
exec.prestart += "jib addm ${uniq_epair} ${external_interface}";
|
||||
exec.prestart += "ifconfig e0a_${uniq_epair} description \"vnet host interface for Bastille jail ${jail_name}\"";
|
||||
exec.poststop += "jib destroy ${uniq_epair}";
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
checkyesno() {
|
||||
## copied from /etc/rc.subr -- cedwards (20231125)
|
||||
## issue #368 (lowercase values should be parsed)
|
||||
|
||||
@@ -34,30 +34,70 @@
|
||||
. /usr/local/etc/bastille/bastille.conf
|
||||
|
||||
usage() {
|
||||
error_exit "Usage: bastille console TARGET [user]"
|
||||
error_notify "Usage: bastille console [option(s)] TARGET [user]"
|
||||
cat << EOF
|
||||
Options:
|
||||
|
||||
-a | --auto Auto mode. Start/stop jail(s) if required.
|
||||
-x | --debug Enable debug mode.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Handle special-case commands first.
|
||||
case "$1" in
|
||||
help|-h|--help)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
# Handle options.
|
||||
AUTO=0
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|--help|help)
|
||||
usage
|
||||
;;
|
||||
-a|--auto)
|
||||
AUTO=1
|
||||
shift
|
||||
;;
|
||||
-x|--debug)
|
||||
enable_debug
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do
|
||||
case ${_opt} in
|
||||
x) enable_debug ;;
|
||||
a) AUTO=1 ;;
|
||||
*) error_exit "Unknown Option: \"${1}\"" ;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 1 ]; then
|
||||
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
bastille_root_check
|
||||
TARGET="${1}"
|
||||
USER="${2}"
|
||||
|
||||
USER="${1}"
|
||||
bastille_root_check
|
||||
set_target_single "${TARGET}"
|
||||
check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then
|
||||
bastille start "${TARGET}"
|
||||
else
|
||||
error_notify "Jail is not running."
|
||||
error_exit "Use [-a|--auto] to auto-start the jail."
|
||||
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 "${TARGET}" id "${USER}" >/dev/null 2>&1; then
|
||||
USER_SHELL="$(jexec -l "${TARGET}" 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}" $LOGIN -f "${USER}"
|
||||
if jexec -l "${TARGET}" grep -qwF "${USER_SHELL}" /etc/shells; then
|
||||
jexec -l "${TARGET}" $LOGIN -f "${USER}"
|
||||
else
|
||||
echo "Invalid shell for user ${USER}"
|
||||
fi
|
||||
@@ -70,7 +110,7 @@ validate_user() {
|
||||
}
|
||||
|
||||
check_fib() {
|
||||
fib=$(grep 'exec.fib' "${bastille_jailsdir}/${_jail}/jail.conf" | awk '{print $3}' | sed 's/\;//g')
|
||||
fib=$(grep 'exec.fib' "${bastille_jailsdir}/${TARGET}/jail.conf" | awk '{print $3}' | sed 's/\;//g')
|
||||
if [ -n "${fib}" ]; then
|
||||
_setfib="setfib -F ${fib}"
|
||||
else
|
||||
@@ -78,15 +118,12 @@ check_fib() {
|
||||
fi
|
||||
}
|
||||
|
||||
for _jail in ${JAILS}; do
|
||||
info "[${_jail}]:"
|
||||
LOGIN="$(jexec -l "${_jail}" which login)"
|
||||
if [ -n "${USER}" ]; then
|
||||
validate_user
|
||||
else
|
||||
check_fib
|
||||
LOGIN="$(jexec -l "${_jail}" which login)"
|
||||
${_setfib} jexec -l "${_jail}" $LOGIN -f root
|
||||
fi
|
||||
echo
|
||||
done
|
||||
info "[${TARGET}]:"
|
||||
LOGIN="$(jexec -l "${TARGET}" which login)"
|
||||
if [ -n "${USER}" ]; then
|
||||
validate_user
|
||||
else
|
||||
check_fib
|
||||
LOGIN="$(jexec -l "${TARGET}" which login)"
|
||||
${_setfib} jexec -l "${TARGET}" $LOGIN -f root
|
||||
fi
|
||||
|
||||
@@ -34,49 +34,64 @@
|
||||
. /usr/local/etc/bastille/bastille.conf
|
||||
|
||||
usage() {
|
||||
error_exit "Usage: bastille cp [OPTION] TARGET HOST_PATH CONTAINER_PATH"
|
||||
error_notify "Usage: bastille cp [option(s)] TARGET HOST_PATH JAIL_PATH"
|
||||
cat << EOF
|
||||
Options:
|
||||
|
||||
-q | --quiet Suppress output.
|
||||
-x | --debug Enable debug mode.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
CPSOURCE="${1}"
|
||||
CPDEST="${2}"
|
||||
# Handle options.
|
||||
OPTION="-av"
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|--help|help)
|
||||
usage
|
||||
;;
|
||||
-q|--quiet)
|
||||
OPTION="-a"
|
||||
shift
|
||||
;;
|
||||
-x|--debug)
|
||||
enable_debug
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do
|
||||
case ${_opt} in
|
||||
q) OPTION="-a" ;;
|
||||
x) enable_debug ;;
|
||||
*) error_exit "Unknown Option: \"${1}\"" ;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Handle special-case commands first.
|
||||
case "$1" in
|
||||
help|-h|--help)
|
||||
usage
|
||||
;;
|
||||
-q|--quiet)
|
||||
OPTION="${1}"
|
||||
CPSOURCE="${2}"
|
||||
CPDEST="${3}"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $# -ne 2 ]; then
|
||||
if [ "$#" -ne 3 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
bastille_root_check
|
||||
TARGET="${1}"
|
||||
HOST_PATH="${2}"
|
||||
JAIL_PATH="${3}"
|
||||
|
||||
case "${OPTION}" in
|
||||
-q|--quiet)
|
||||
OPTION="-a"
|
||||
;;
|
||||
*)
|
||||
OPTION="-av"
|
||||
;;
|
||||
esac
|
||||
bastille_root_check
|
||||
set_target "${TARGET}"
|
||||
|
||||
for _jail in ${JAILS}; do
|
||||
info "[${_jail}]:"
|
||||
bastille_jail_path="${bastille_jailsdir}/${_jail}/root"
|
||||
cp "${OPTION}" "${CPSOURCE}" "${bastille_jail_path}/${CPDEST}"
|
||||
RETURN="$?"
|
||||
if [ "${TARGET}" = "ALL" ]; then
|
||||
# Display the return status for reference
|
||||
echo -e "Returned: ${RETURN}\n"
|
||||
else
|
||||
echo
|
||||
return "${RETURN}"
|
||||
host_path="${HOST_PATH}"
|
||||
jail_path="$(echo ${bastille_jailsdir}/${_jail}/root/${JAIL_PATH} | sed 's#//#/#g')"
|
||||
if ! cp "${OPTION}" "${host_path}" "${jail_path}"; then
|
||||
error_continue "CP failed: ${host_path} -> ${jail_path}"
|
||||
fi
|
||||
done
|
||||
done
|
||||
@@ -41,12 +41,13 @@ usage() {
|
||||
cat << EOF
|
||||
Options:
|
||||
|
||||
-E | --empty -- Creates an empty container, intended for custom jail builds (thin/thick/linux or unsupported).
|
||||
-L | --linux -- This option is intended for testing with Linux jails, this is considered experimental.
|
||||
-T | --thick -- Creates a thick container, they consume more space as they are self contained and independent.
|
||||
-V | --vnet -- Enables VNET, VNET containers are attached to a virtual bridge interface for connectivity.
|
||||
-C | --clone -- Creates a clone container, they are duplicates of the base release, consume low space and preserves changing data.
|
||||
-B | --bridge -- Enables VNET, VNET containers are attached to a specified, already existing external bridge.
|
||||
-M | --static-mac -- Generate a static MAC address for jail (VNET only).
|
||||
-E | --empty -- Creates an empty container, intended for custom jail builds (thin/thick/linux or unsupported).
|
||||
-L | --linux -- This option is intended for testing with Linux jails, this is considered experimental.
|
||||
-T | --thick -- Creates a thick container, they consume more space as they are self contained and independent.
|
||||
-V | --vnet -- Enables VNET, VNET containers are attached to a virtual bridge interface for connectivity.
|
||||
-C | --clone -- Creates a clone container, they are duplicates of the base release, consume low space and preserves changing data.
|
||||
-B | --bridge -- Enables VNET, VNET containers are attached to a specified, already existing external bridge.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
@@ -67,6 +68,8 @@ validate_name() {
|
||||
error_exit "Container names may not begin with (-|_) characters!"
|
||||
elif [ "${NAME_VERIFY}" != "${NAME_SANITY}" ]; then
|
||||
error_exit "Container names may not contain special characters!"
|
||||
elif echo "${NAME_VERIFY}" | grep -qE '^[0-9]+$'; then
|
||||
error_exit "Container names may not contain only digits."
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -229,7 +232,7 @@ generate_vnet_jail_conf() {
|
||||
else
|
||||
devfs_ruleset_value=13
|
||||
fi
|
||||
NETBLOCK=$(generate_vnet_jail_netblock "$NAME" "${VNET_JAIL_BRIDGE}" "${bastille_jail_conf_interface}")
|
||||
NETBLOCK=$(generate_vnet_jail_netblock "$NAME" "${VNET_JAIL_BRIDGE}" "${bastille_jail_conf_interface}" "${STATIC_MAC}")
|
||||
cat << EOF > "${bastille_jail_conf}"
|
||||
${NAME} {
|
||||
enforce_statfs = 2;
|
||||
@@ -630,10 +633,15 @@ THICK_JAIL=""
|
||||
CLONE_JAIL=""
|
||||
VNET_JAIL=""
|
||||
LINUX_JAIL=""
|
||||
STATIC_MAC=""
|
||||
|
||||
# Handle and parse options
|
||||
while [ $# -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-M|--static-mac)
|
||||
STATIC_MAC="1"
|
||||
shift
|
||||
;;
|
||||
-E|--empty)
|
||||
EMPTY_JAIL="1"
|
||||
shift
|
||||
|
||||
197
usr/local/share/bastille/etcupdate.sh
Normal file
197
usr/local/share/bastille/etcupdate.sh
Normal file
@@ -0,0 +1,197 @@
|
||||
#!/bin/sh
|
||||
# Copyright (c) 2018-2025, Christer Edwards <christer.edwards@gmail.com>
|
||||
# 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/common.sh
|
||||
. /usr/local/etc/bastille/bastille.conf
|
||||
|
||||
usage() {
|
||||
error_notify "Usage: bastille etcupdate [option(s)] [bootstrap|TARGET] [diff|resolve|update RELEASE]"
|
||||
cat << EOF
|
||||
Options:
|
||||
|
||||
-d | --dry-run Show output, but do not apply.
|
||||
-f | --force Force a re-bootstrap of a RELEASE.
|
||||
-x | --debug Enable debug mode.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
bootstrap_etc_release() {
|
||||
local _release="${1}"
|
||||
local _current="$(sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives | awk -F': ' '{print $2}')"
|
||||
if ! ls -A "${bastille_releasesdir}/${_release}/usr/src" 2>/dev/null; then
|
||||
sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives=src
|
||||
if ! bastille bootstrap "${_release}" > /dev/null; then
|
||||
sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}"
|
||||
error_exit "Failed to bootstrap etcupdate: ${_release}"
|
||||
else
|
||||
sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
bootstrap_etc_tarball() {
|
||||
local _release="${1}"
|
||||
if [ ! -f ${bastille_cachedir}/${_release}.tbz2 ]; then
|
||||
echo "Building tarball, please wait..."
|
||||
if ! etcupdate build -d /tmp/etcupdate -s ${bastille_releasesdir}/${_release}/usr/src ${bastille_cachedir}/${_release}.tbz2; then
|
||||
error_exit "Failed to build etcupdate tarball \"${_release}.tbz2\""
|
||||
else
|
||||
info "Etcupdate bootstrap complete: ${_release}"
|
||||
fi
|
||||
elif [ -f ${bastille_cachedir}/${_release}.tbz2 ] && [ "${FORCE}" -eq 1 ]; then
|
||||
rm -f "${bastille_cachedir}/${_release}.tbz2"
|
||||
echo "Building tarball, please wait..."
|
||||
if ! etcupdate build -d /tmp/etcupdate -s ${bastille_releasesdir}/${_release}/usr/src ${bastille_cachedir}/${_release}.tbz2; then
|
||||
error_exit "Failed to build etcupdate tarball: ${_release}.tbz2"
|
||||
else
|
||||
info "Etcupdate bootstrap complete: ${_release}"
|
||||
fi
|
||||
else
|
||||
info "Etcupdate release has already been prepared for application: ${_release}"
|
||||
fi
|
||||
}
|
||||
|
||||
diff_review() {
|
||||
local _jail="${1}"
|
||||
if [ "${DRY_RUN}" -eq 1 ]; then
|
||||
warn "Warning: diff mode does not support [-d|--dryrun]"
|
||||
fi
|
||||
info "[${_jail}]: etcupdate --diff mode"
|
||||
etcupdate diff -D "${bastille_jailsdir}/${_jail}/root"
|
||||
}
|
||||
|
||||
resolve_conflicts() {
|
||||
local _jail="${1}"
|
||||
if [ "${DRY_RUN}" -eq 1 ]; then
|
||||
warn "Warning: resolve mode does not support [-d|--dryrun]"
|
||||
fi
|
||||
info "[${_jail}]: etcupdate resolve"
|
||||
etcupdate resolve -D "${bastille_jailsdir}/${_jail}/root"
|
||||
}
|
||||
|
||||
update_jail_etc() {
|
||||
local _jail="${1}"
|
||||
local _release="${2}"
|
||||
if [ ! -f ${bastille_cachedir}/${_release}.tbz2 ]; then
|
||||
error_exit "Error: Please run \"bastille etcupdate bootstrap RELEASE\" first."
|
||||
fi
|
||||
if [ "${DRY_RUN}" -eq 1 ]; then
|
||||
info "[${_jail}]: etcupdate update --dry-run"
|
||||
etcupdate -n -D "${bastille_jailsdir}/${_jail}/root" -t ${bastille_cachedir}/${_release}.tbz2
|
||||
else
|
||||
info "[${_jail}]: etcupdate update"
|
||||
etcupdate -D "${bastille_jailsdir}/${_jail}/root" -t ${bastille_cachedir}/${_release}.tbz2
|
||||
fi
|
||||
}
|
||||
|
||||
# Handle options.
|
||||
DRY_RUN=0
|
||||
FORCE=0
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|--help|help)
|
||||
usage
|
||||
;;
|
||||
-d|--dry-run)
|
||||
DRY_RUN=1
|
||||
shift
|
||||
;;
|
||||
-f|--force)
|
||||
FORCE=1
|
||||
shift
|
||||
;;
|
||||
-x|--debug)
|
||||
enable_debug
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do
|
||||
case ${_opt} in
|
||||
d) DRY_RUN=1 ;;
|
||||
f) FORCE=1 ;;
|
||||
x) enable_debug ;;
|
||||
*) error_exit "Unknown Option: \"${1}\"" ;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
# Main commands
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
bootstrap)
|
||||
if [ -z "${2}" ]; then
|
||||
usage
|
||||
else
|
||||
RELEASE="${2}"
|
||||
bootstrap_etc_release "${RELEASE}"
|
||||
bootstrap_etc_tarball "${RELEASE}"
|
||||
shift "$#"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
TARGET="${1}"
|
||||
ACTION="${2}"
|
||||
RELEASE="${3}"
|
||||
set_target_single "${TARGET}"
|
||||
case "${ACTION}" in
|
||||
diff)
|
||||
diff_review "${TARGET}"
|
||||
shift "$#"
|
||||
;;
|
||||
resolve)
|
||||
resolve_conflicts "${TARGET}"
|
||||
shift "$#"
|
||||
;;
|
||||
update)
|
||||
if [ -z "${RELEASE}" ]; then
|
||||
usage
|
||||
else
|
||||
update_jail_etc "${TARGET}" "${RELEASE}"
|
||||
shift "$#"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
error_exit "Unknown action: \"${ACTION}\""
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
done
|
||||
@@ -34,29 +34,41 @@
|
||||
. /usr/local/etc/bastille/bastille.conf
|
||||
|
||||
usage() {
|
||||
error_exit "Usage: bastille htop [option(s)] TARGET"
|
||||
error_notify "Usage: bastille htop [option(s)] TARGET"
|
||||
cat << EOF
|
||||
Options:
|
||||
|
||||
-f | --force -- Start the jail if it is stopped.
|
||||
-a | --auto Auto mode. Start/stop jail(s) if required.
|
||||
-x | --debug Enable debug mode.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Handle options.
|
||||
FORCE=0
|
||||
AUTO=0
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|--help|help)
|
||||
usage
|
||||
;;
|
||||
-f|--force)
|
||||
FORCE=1
|
||||
-a|--auto)
|
||||
AUTO=1
|
||||
shift
|
||||
;;
|
||||
-x|--debug)
|
||||
enable_debug
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
error_exit "Unknown option: \"${1}\""
|
||||
for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do
|
||||
case ${_opt} in
|
||||
a) AUTO=1 ;;
|
||||
x) enable_debug ;;
|
||||
*) error_exit "Unknown Option: \"${1}\""
|
||||
esac
|
||||
done
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
@@ -74,15 +86,14 @@ bastille_root_check
|
||||
set_target_single "${TARGET}"
|
||||
|
||||
info "[${TARGET}]:"
|
||||
check_target_is_running "${TARGET}" || if [ "${FORCE}" -eq 1 ]; then
|
||||
check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then
|
||||
bastille start "${TARGET}"
|
||||
else
|
||||
error_notify "Jail is not running."
|
||||
error_continue "Use [-f|--force] to force start the jail."
|
||||
error_continue "Use [-a|--auto] to auto-start the jail."
|
||||
fi
|
||||
|
||||
bastille_jail_path="${bastille_jailsdir}/${TARGET}/root"
|
||||
if [ ! -x "${bastille_jail_path}/usr/local/bin/htop" ]; then
|
||||
if [ ! -x "${bastille_jailsdir}/${TARGET}/root/usr/local/bin/htop" ]; then
|
||||
error_notify "htop not found on ${TARGET}."
|
||||
elif [ -x "${bastille_jail_path}/usr/local/bin/htop" ]; then
|
||||
jexec -l ${TARGET} /usr/local/bin/htop
|
||||
|
||||
103
usr/local/share/bastille/jcp.sh
Normal file
103
usr/local/share/bastille/jcp.sh
Normal file
@@ -0,0 +1,103 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
# Copyright (c) 2018-2025, Christer Edwards <christer.edwards@gmail.com>
|
||||
# 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/common.sh
|
||||
. /usr/local/etc/bastille/bastille.conf
|
||||
|
||||
usage() {
|
||||
error_notify "Usage: bastille jcp [option(s)] SOURCE_JAIL JAIL_PATH DEST_JAIL JAIL_PATH"
|
||||
cat << EOF
|
||||
Options:
|
||||
|
||||
-q | --quiet Suppress output.
|
||||
-x | --debug Enable debug mode.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Handle options.
|
||||
OPTION="-av"
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|--help|help)
|
||||
usage
|
||||
;;
|
||||
-q|--quiet)
|
||||
OPTION="-a"
|
||||
shift
|
||||
;;
|
||||
-x|--debug)
|
||||
enable_debug
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do
|
||||
case ${_opt} in
|
||||
q) OPTION="-a" ;;
|
||||
x) enable_debug ;;
|
||||
*) error_exit "Unknown Option: \"${1}\"" ;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$#" -ne 4 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
SOURCE_TARGET="${1}"
|
||||
SOURCE_PATH="${2}"
|
||||
DEST_TARGET="${3}"
|
||||
DEST_PATH="${4}"
|
||||
|
||||
bastille_root_check
|
||||
set_target_single "${SOURCE_TARGET}" && SOURCE_TARGET="${TARGET}"
|
||||
set_target "${DEST_TARGET}" && DEST_TARGET="${JAILS}"
|
||||
|
||||
for _jail in ${DEST_TARGET}; do
|
||||
if [ "${_jail}" = "${SOURCE_TARGET}" ]; then
|
||||
continue
|
||||
else
|
||||
info "[${_jail}]:"
|
||||
source_path="$(echo ${bastille_jailsdir}/${SOURCE_TARGET}/root/${SOURCE_PATH} | sed 's#//#/#g')"
|
||||
dest_path="$(echo ${bastille_jailsdir}/${_jail}/root/${DEST_PATH} | sed 's#//#/#g')"
|
||||
if ! cp "${OPTION}" "${source_path}" "${dest_path}"; then
|
||||
error_continue "JCP failed: ${source_path} -> ${dest_path}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
@@ -64,7 +64,8 @@ list_all(){
|
||||
MAX_LENGTH_JID=${MAX_LENGTH_JID:-3}
|
||||
MAX_LENGTH_JAIL_IP=$(find ${bastille_jailsdir}/*/jail.conf -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 sed -n "s/^[ ]*ip[4,6].addr[ ]*=[ ]*\(.*\);$/\1 /p" | sed 's/\// /g' | awk '{ print length($1) }' | sort -nr | head -n 1)
|
||||
MAX_LENGTH_JAIL_IP=${MAX_LENGTH_JAIL_IP:-10}
|
||||
MAX_LENGTH_JAIL_VNET_IP=$(find ${bastille_jailsdir}/*/jail.conf -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -l "vnet;" | grep -h "ifconfig_vnet0=" "$(sed -n "s/\(.*\)jail.conf$/\1root\/etc\/rc.conf/p")" | sed -n "s/^ifconfig_vnet0=\"\(.*\)\"$/\1/p"| sed "s/\// /g" | awk '{ if ($1 ~ /^[inet|inet6]/) print length($2); else print 15 }' | sort -nr | head -n 1)
|
||||
# shellcheck disable=SC2046
|
||||
MAX_LENGTH_JAIL_VNET_IP="$(find ${bastille_jailsdir}/*/jail.conf -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -l "vnet;" | grep -h "ifconfig_vnet0=" $(sed -n "s/\(.*\)jail.conf$/\1root\/etc\/rc.conf/p") | sed -n "s/^ifconfig_vnet0=\"\(.*\)\"$/\1/p"| sed "s/\// /g" | awk '{ if ($1 ~ /^[inet|inet6]/) print length($2); else print 15 }' | sort -nr | head -n 1)"
|
||||
MAX_LENGTH_JAIL_VNET_IP=${MAX_LENGTH_JAIL_VNET_IP:-10}
|
||||
if [ "${MAX_LENGTH_JAIL_VNET_IP}" -gt "${MAX_LENGTH_JAIL_IP}" ]; then MAX_LENGTH_JAIL_IP=${MAX_LENGTH_JAIL_VNET_IP}; fi
|
||||
if [ "${MAX_LENGTH_JAIL_IP}" -lt 10 ]; then MAX_LENGTH_JAIL_IP=10; fi
|
||||
@@ -75,11 +76,13 @@ list_all(){
|
||||
MAX_LENGTH_JAIL_PORTS=${MAX_LENGTH_JAIL_PORTS:-15}
|
||||
if [ "${MAX_LENGTH_JAIL_PORTS}" -lt 15 ]; then MAX_LENGTH_JAIL_PORTS=15; fi
|
||||
if [ "${MAX_LENGTH_JAIL_PORTS}" -gt 30 ]; then MAX_LENGTH_JAIL_PORTS=30; fi
|
||||
MAX_LENGTH_JAIL_RELEASE=$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/releases/.*/root/.bastille.*nullfs" | grep -hE "^USERLAND_VERSION=" "$(sed -n "s/^\(.*\) \/.*$/\1\/bin\/freebsd-version/p" | awk '!_[$0]++')" | sed "s/[\"\'\^]//g;s/ .*$//g" | sed -n "s/^USERLAND_VERSION=\(.*\)$/\1/p" | awk '{ print length($0) }' | sort -nr | head -n 1)
|
||||
# shellcheck disable=SC2046
|
||||
MAX_LENGTH_JAIL_RELEASE="$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/releases/.*/root/.bastille.*nullfs" | grep -hE "^USERLAND_VERSION=" $(sed -n "s/^\(.*\) \/.*$/\1\/bin\/freebsd-version/p" | awk '!_[$0]++') | sed "s/[\"\'\^]//g;s/ .*$//g" | sed -n "s/^USERLAND_VERSION=\(.*\)$/\1/p" | awk '{ print length($0) }' | sort -nr | head -n 1)"
|
||||
MAX_LENGTH_JAIL_RELEASE=${MAX_LENGTH_JAIL_RELEASE:-7}
|
||||
MAX_LENGTH_THICK_JAIL_RELEASE=$(find ${bastille_jailsdir}/*/root/bin/freebsd-version -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -hE "^USERLAND_VERSION=" | sed "s/[\"\'\^]//g;s/ .*$//g" | sed -n "s/^USERLAND_VERSION=\(.*\)$/\1/p" | awk '{ print length($0) }' | sort -nr | head -n 1)
|
||||
MAX_LENGTH_THICK_JAIL_RELEASE=${MAX_LENGTH_THICK_JAIL_RELEASE:-7}
|
||||
MAX_LENGTH_LINUX_JAIL_RELEASE=$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/jails/.*/root/proc.*linprocfs" | grep -hE "^NAME=|^VERSION_ID=|^VERSION_CODENAME=" "$(sed -n "s/^linprocfs *\(.*\)\/.*$/\1\/etc\/os-release/p")" 2> /dev/null | sed "s/\"//g" | sed "s/ GNU\/Linux//g" | sed "N;N;s/\n/;/g" | sed -n "s/^NAME=\(.*\);VERSION_ID=\(.*\);VERSION_CODENAME=\(.*\)$/\1 \2 (\3)/p" | awk '{ print length($0) }' | sort -nr | head -n 1)
|
||||
# shellcheck disable=SC2046
|
||||
MAX_LENGTH_LINUX_JAIL_RELEASE="$(find ${bastille_jailsdir}/*/fstab -maxdepth 1 -type f -print0 2> /dev/null | xargs -r0 -P0 grep -h "/jails/.*/root/proc.*linprocfs" | grep -hE "^NAME=|^VERSION_ID=|^VERSION_CODENAME=" $(sed -n "s/^linprocfs *\(.*\)\/.*$/\1\/etc\/os-release/p") 2> /dev/null | sed "s/\"//g" | sed "s/ GNU\/Linux//g" | sed "N;N;s/\n/;/g" | sed -n "s/^NAME=\(.*\);VERSION_ID=\(.*\);VERSION_CODENAME=\(.*\)$/\1 \2 (\3)/p" | awk '{ print length($0) }' | sort -nr | head -n 1)"
|
||||
MAX_LENGTH_LINUX_JAIL_RELEASE=${MAX_LENGTH_LINUX_JAIL_RELEASE:-7}
|
||||
if [ "${MAX_LENGTH_THICK_JAIL_RELEASE}" -gt "${MAX_LENGTH_JAIL_RELEASE}" ]; then MAX_LENGTH_JAIL_RELEASE=${MAX_LENGTH_THICK_JAIL_RELEASE}; fi
|
||||
if [ "${MAX_LENGTH_LINUX_JAIL_RELEASE}" -gt "${MAX_LENGTH_JAIL_RELEASE}" ]; then MAX_LENGTH_JAIL_RELEASE=${MAX_LENGTH_LINUX_JAIL_RELEASE}; fi
|
||||
|
||||
@@ -34,15 +34,24 @@
|
||||
. /usr/local/etc/bastille/bastille.conf
|
||||
|
||||
usage() {
|
||||
error_exit "Usage: bastille mount TARGET HOST_PATH JAIL_PATH [filesystem_type options dump pass_number]"
|
||||
error_exit "Usage: bastille mount [option(s)] TARGET HOST_PATH JAIL_PATH [filesystem_type options dump pass_number]"
|
||||
}
|
||||
|
||||
# Handle special-case commands first.
|
||||
case "${1}" in
|
||||
help|-h|--help)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
# Handle options.
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|--help|help)
|
||||
usage
|
||||
;;
|
||||
--*|-*)
|
||||
error_notify "Unknown Option."
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$#" -lt 3 ] || [ "$#" -gt 7 ]; then
|
||||
usage
|
||||
@@ -91,8 +100,8 @@ elif [ ! -e "${_hostpath}" ] || [ "${_type}" != "nullfs" ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
# Mount permissions,options need to start with "ro" or "rw"
|
||||
if ! echo "${_perms}" | grep -Eq 'r[w|o],.*$'; then
|
||||
# Mount permissions,options must include one of "ro, rw, rq, sw, xx"
|
||||
if ! echo "${_perms}" | grep -Eq '(ro|rw|rq|sw|xx)(,.*)?$'; then
|
||||
error_notify "Detected invalid mount permissions in FSTAB."
|
||||
warn "Format: /host/path /jail/path nullfs ro 0 0"
|
||||
warn "Read: ${_fstab}"
|
||||
@@ -117,7 +126,7 @@ for _jail in ${JAILS}; do
|
||||
|
||||
# Check if mount point has already been added
|
||||
_existing_mount="$(echo ${_fullpath_fstab} 2>/dev/null | sed 's#\\#\\\\#g')"
|
||||
if grep -Eq "[[:blank:]]${_existing_mount}.*[[:blank:]]" "${bastille_jailsdir}/${_jail}/fstab"; then
|
||||
if grep -Eq "[[:blank:]]${_existing_mount}[[:blank:]]" "${bastille_jailsdir}/${_jail}/fstab"; then
|
||||
warn "Mountpoint already present in ${bastille_jailsdir}/${_jail}/fstab"
|
||||
grep -E "[[:blank:]]${_existing_mount}" "${bastille_jailsdir}/${_jail}/fstab"
|
||||
continue
|
||||
|
||||
@@ -34,46 +34,64 @@
|
||||
. /usr/local/etc/bastille/bastille.conf
|
||||
|
||||
usage() {
|
||||
error_exit "Usage: bastille rcp [OPTION] TARGET CONTAINER_PATH HOST_PATH"
|
||||
error_notify "Usage: bastille rcp [option(s)] TARGET JAIL_PATH HOST_PATH"
|
||||
cat << EOF
|
||||
Options:
|
||||
|
||||
-q | --quiet Suppress output.
|
||||
-x | --debug Enable debug mode.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
CPSOURCE="${1}"
|
||||
CPDEST="${2}"
|
||||
|
||||
# Handle special-case commands first.
|
||||
case "$1" in
|
||||
help|-h|--help)
|
||||
usage
|
||||
;;
|
||||
-q|--quiet)
|
||||
OPTION="${1}"
|
||||
CPSOURCE="${2}"
|
||||
CPDEST="${3}"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $# -ne 2 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ "${TARGET}" = "ALL" ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
case "${OPTION}" in
|
||||
-q|--quiet)
|
||||
OPTION="-a"
|
||||
;;
|
||||
*)
|
||||
OPTION="-av"
|
||||
;;
|
||||
esac
|
||||
|
||||
for _jail in ${JAILS}; do
|
||||
info "[${_jail}]:"
|
||||
bastille_jail_path="${bastille_jailsdir}/${_jail}/root"
|
||||
cp "${OPTION}" "${bastille_jail_path}/${CPSOURCE}" "${CPDEST}"
|
||||
RETURN="$?"
|
||||
echo
|
||||
return "${RETURN}"
|
||||
# Handle options.
|
||||
OPTION="-av"
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|--help|help)
|
||||
usage
|
||||
;;
|
||||
-q|--quiet)
|
||||
OPTION="-a"
|
||||
shift
|
||||
;;
|
||||
-x|--debug)
|
||||
enable_debug
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do
|
||||
case ${_opt} in
|
||||
q) OPTION="-a" ;;
|
||||
x) enable_debug ;;
|
||||
*) error_exit "Unknown Option: \"${1}\"" ;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$#" -ne 3 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
TARGET="${1}"
|
||||
JAIL_PATH="${2}"
|
||||
HOST_PATH="${3}"
|
||||
|
||||
bastille_root_check
|
||||
set_target_single "${TARGET}"
|
||||
|
||||
info "[${TARGET}]:"
|
||||
|
||||
host_path="${HOST_PATH}"
|
||||
jail_path="$(echo ${bastille_jailsdir}/${TARGET}/root/${JAIL_PATH} | sed 's#//#/#g')"
|
||||
|
||||
if ! cp "${OPTION}" "${jail_path}" "${host_path}"; then
|
||||
error_exit "RCP failed: ${jail_path} -> ${host_path}"
|
||||
fi
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
# Copyright (c) 2018-2025, Christer Edwards <christer.edwards@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
@@ -34,11 +32,62 @@
|
||||
. /usr/local/etc/bastille/bastille.conf
|
||||
|
||||
usage() {
|
||||
error_exit "Usage: bastille rename TARGET NEW_NAME"
|
||||
error_notify "Usage: bastille rename [option(s)] TARGET NEW_NAME"
|
||||
cat << EOF
|
||||
Options:
|
||||
|
||||
-a | --auto Auto mode. Start/stop jail(s) if required.
|
||||
-x | --debug Enable debug mode.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Handle options.
|
||||
AUTO=0
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|--help|help)
|
||||
usage
|
||||
;;
|
||||
-a|--auto)
|
||||
AUTO=1
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do
|
||||
case ${_opt} in
|
||||
a) AUTO=1 ;;
|
||||
x) enable_debug ;;
|
||||
*) error_exit "Unknown Option: \"${1}\""
|
||||
esac
|
||||
done
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$#" -ne 2 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
TARGET="${1}"
|
||||
NEWNAME="${2}"
|
||||
|
||||
bastille_root_check
|
||||
set_target_single "${TARGET}"
|
||||
check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then
|
||||
bastille stop "${TARGET}"
|
||||
else
|
||||
error_notify "Jail is running."
|
||||
error_exit "Use [-a|--auto] to auto-stop the jail."
|
||||
fi
|
||||
|
||||
validate_name() {
|
||||
local NAME_VERIFY=${NEWNAME}
|
||||
local NAME_VERIFY="${NEWNAME}"
|
||||
local NAME_SANITY="$(echo "${NAME_VERIFY}" | tr -c -d 'a-zA-Z0-9-_')"
|
||||
if [ -n "$(echo "${NAME_SANITY}" | awk "/^[-_].*$/" )" ]; then
|
||||
error_exit "Container names may not begin with (-|_) characters!"
|
||||
@@ -47,44 +96,64 @@ validate_name() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Handle special-case commands first
|
||||
case "$1" in
|
||||
help|-h|--help)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
bastille_root_check
|
||||
|
||||
NEWNAME="${1}"
|
||||
|
||||
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}"
|
||||
# Rename vnet interface
|
||||
sed -i '' "/vnet.interface/s|_${TARGET}\";|_${NEWNAME}\";|" "${JAIL_CONFIG}"
|
||||
sed -i '' "/ifconfig/s|_${TARGET}|_${NEWNAME}|" "${JAIL_CONFIG}"
|
||||
local _jail_conf="${bastille_jailsdir}/${NEWNAME}/jail.conf"
|
||||
local _rc_conf="${bastille_jailsdir}/${NEWNAME}/root/etc/rc.conf"
|
||||
if [ -f "${_jail_conf}" ]; then
|
||||
if ! grep -qw "path = ${bastille_jailsdir}/${NEWNAME}/root;" "${_jail_conf}"; then
|
||||
sed -i '' "s|host.hostname.*=.*${TARGET};|host.hostname = ${NEWNAME};|" "${_jail_conf}"
|
||||
sed -i '' "s|exec.consolelog.*=.*;|exec.consolelog = ${bastille_logsdir}/${NEWNAME}_console.log;|" "${_jail_conf}"
|
||||
sed -i '' "s|path.*=.*;|path = ${bastille_jailsdir}/${NEWNAME}/root;|" "${_jail_conf}"
|
||||
sed -i '' "s|mount.fstab.*=.*;|mount.fstab = ${bastille_jailsdir}/${NEWNAME}/fstab;|" "${_jail_conf}"
|
||||
sed -i '' "s|${TARGET}.*{|${NEWNAME} {|" "${_jail_conf}"
|
||||
fi
|
||||
if grep -qo "vnet;" "${_jail_conf}"; then
|
||||
update_jailconf_vnet
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
update_fstab() {
|
||||
# Update fstab to use the new name
|
||||
FSTAB_CONFIG="${bastille_jailsdir}/${NEWNAME}/fstab"
|
||||
if [ -f "${FSTAB_CONFIG}" ]; then
|
||||
sed -i '' "s|${bastille_jailsdir}/${TARGET}|${bastille_jailsdir}/${NEWNAME}|g" "${FSTAB_CONFIG}"
|
||||
fi
|
||||
update_jailconf_vnet() {
|
||||
local _jail_conf="${bastille_jailsdir}/${NEWNAME}/jail.conf"
|
||||
local _rc_conf="${bastille_jailsdir}/${NEWNAME}/root/etc/rc.conf"
|
||||
# Change epair name (if needed)
|
||||
local _if_list="$(grep -Eo 'epair[0-9]+|bastille[0-9]+' ${_jail_conf} | sort -u)"
|
||||
for _if in ${_if_list}; do
|
||||
if echo ${_if} | grep -Eoq 'epair[0-9]+'; then
|
||||
# Check if epair name = jail name
|
||||
local _epair_num="$(grep -Eo -m 1 "epair[0-9]+" "${_jail_conf}" | grep -Eo "[0-9]+")"
|
||||
if grep -E "epair[0-9]+a" "${_jail_conf}" | grep -Eo "e[0-9]+a_${TARGET}"; then
|
||||
local _target_host_epair="$(grep -Eo -m 1 "e[0-9]+a_${TARGET}" "${_jail_conf}")"
|
||||
local _target_jail_epair="$(grep -Eo -m 1 "e[0-9]+b_${TARGET}" "${_jail_conf}")"
|
||||
else
|
||||
local _target_host_epair="$(grep -Eo -m 1 "epair[0-9]+a" "${_jail_conf}")"
|
||||
local _target_jail_epair="$(grep -Eo -m 1 "epair[0-9]+b" "${_jail_conf}")"
|
||||
fi
|
||||
if [ "$(echo -n "e${_epair_num}a_${NEWNAME}" | awk '{print length}')" -lt 16 ]; then
|
||||
# Generate new epair name
|
||||
local _new_host_epair="e${_epair_num}a_${NEWNAME}"
|
||||
local _new_jail_epair="e${_epair_num}b_${NEWNAME}"
|
||||
else
|
||||
local _new_host_epair="epair${_epair_num}a"
|
||||
local _new_jail_epair="epair${_epair_num}b"
|
||||
fi
|
||||
# Replace host epair name in jail.conf
|
||||
sed -i '' "s|up name ${_target_host_epair}|up name ${_new_host_epair}|g" "${_jail_conf}"
|
||||
sed -i '' "s|${_target_host_epair} ether|${_new_host_epair} ether|g" "${_jail_conf}"
|
||||
sed -i '' "s|deletem ${_target_host_epair}|deletem ${_new_host_epair}|g" "${_jail_conf}"
|
||||
sed -i '' "s|${_target_host_epair} destroy|${_new_host_epair} destroy|g" "${_jail_conf}"
|
||||
sed -i '' "s|${_target_host_epair} description|${_new_host_epair} description|g" "${_jail_conf}"
|
||||
# Replace jail epair name in jail.conf
|
||||
sed -i '' "s|= ${_target_jail_epair};|= ${_new_jail_epair};|g" "${_jail_conf}"
|
||||
sed -i '' "s|up name ${_target_jail_epair}|up name ${_new_jail_epair}|g" "${_jail_conf}"
|
||||
sed -i '' "s|${_target_jail_epair} ether|${_new_jail_epair} ether|g" "${_jail_conf}"
|
||||
# Replace epair description
|
||||
sed -i '' "s|vnet host interface for Bastille jail ${TARGET}|vnet host interface for Bastille jail ${NEWNAME}|g" "${_jail_conf}"
|
||||
# Replace epair name in /etc/rc.conf
|
||||
sed -i '' "/ifconfig/ s|${_target_jail_epair}|${_new_jail_epair}|g" "${_rc_conf}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
change_name() {
|
||||
@@ -124,24 +193,27 @@ change_name() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# Update jail configuration files accordingly
|
||||
# Update jail conf files
|
||||
update_jailconf
|
||||
update_fstab
|
||||
update_fstab "${TARGET}" "${NEWNAME}"
|
||||
|
||||
# Check exit status and notify
|
||||
if [ "$?" -ne 0 ]; then
|
||||
error_exit "An error has occurred while attempting to rename '${TARGET}'."
|
||||
else
|
||||
info "Renamed '${TARGET}' to '${NEWNAME}' successfully."
|
||||
if [ "${AUTO}" -eq 1 ]; then
|
||||
bastille start "${NEWNAME}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
## validate jail name
|
||||
# Validate NEW_NAME
|
||||
if [ -n "${NEWNAME}" ]; then
|
||||
validate_name
|
||||
fi
|
||||
|
||||
## check if a jail already exists with the new name
|
||||
# Check if a jail already exists with NEW_NAME
|
||||
if [ -d "${bastille_jailsdir}/${NEWNAME}" ]; then
|
||||
error_exit "Jail: ${NEWNAME} already exists."
|
||||
fi
|
||||
|
||||
@@ -38,25 +38,37 @@ usage() {
|
||||
cat << EOF
|
||||
Options:
|
||||
|
||||
-f | --force -- Start the jail if it is stopped.
|
||||
-a | --auto Auto mode. Start/stop jail(s) if required.
|
||||
-x | --debug Enable debug mode.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Handle options.
|
||||
FORCE=0
|
||||
AUTO=0
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|--help|help)
|
||||
usage
|
||||
;;
|
||||
-f|--force)
|
||||
FORCE=1
|
||||
-a|--auto)
|
||||
AUTO=1
|
||||
shift
|
||||
;;
|
||||
-x|--debug)
|
||||
enable_debug
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
error_exit "Unknown option: \"${1}\""
|
||||
for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do
|
||||
case ${_opt} in
|
||||
a) AUTO=1 ;;
|
||||
x) enable_debug ;;
|
||||
*) error_exit "Unknown Option: \"${1}\""
|
||||
esac
|
||||
done
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
@@ -74,10 +86,10 @@ bastille_root_check
|
||||
set_target_single "${TARGET}"
|
||||
|
||||
info "[${TARGET}]:"
|
||||
check_target_is_running "${TARGET}" || if [ "${FORCE}" -eq 1 ]; then
|
||||
check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then
|
||||
bastille start "${TARGET}"
|
||||
else
|
||||
error_notify "Jail is not running."
|
||||
error_continue "Use [-f|--force] to force start the jail."
|
||||
error_continue "Use [-a|--auto] to auto-start the jail."
|
||||
fi
|
||||
jexec -l "${TARGET}" /usr/bin/top
|
||||
|
||||
@@ -34,39 +34,62 @@
|
||||
. /usr/local/etc/bastille/bastille.conf
|
||||
|
||||
usage() {
|
||||
error_exit "Usage: bastille update [release|container|template] | [force]"
|
||||
}
|
||||
error_notify "Usage: bastille update [option(s)] TARGET"
|
||||
cat << EOF
|
||||
Options:
|
||||
|
||||
# Handle special-case commands first.
|
||||
case "$1" in
|
||||
help|-h|--help)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
-a | --auto Auto mode. Start/stop jail(s) if required.
|
||||
-f | --force Force update a release.
|
||||
-x | --debug Enable debug mode.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ $# -gt 2 ] || [ $# -lt 1 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
bastille_root_check
|
||||
# Handle options.
|
||||
OPTION=""
|
||||
AUTO=0
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|--help|help)
|
||||
usage
|
||||
;;
|
||||
-a|--auto)
|
||||
AUTO=1
|
||||
shift
|
||||
;;
|
||||
-f|--force)
|
||||
OPTION="-F"
|
||||
shift
|
||||
;;
|
||||
-x|--debug)
|
||||
enable_debug
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do
|
||||
case ${_opt} in
|
||||
a) AUTO=1 ;;
|
||||
f) OPTION="-F" ;;
|
||||
x) enable_debug ;;
|
||||
*) error_exit "Unknown Option: \"${1}\"" ;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
TARGET="${1}"
|
||||
OPTION="${2}"
|
||||
|
||||
# Handle options
|
||||
case "${OPTION}" in
|
||||
-f|--force)
|
||||
OPTION="-F"
|
||||
;;
|
||||
*)
|
||||
OPTION=
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check for unsupported actions
|
||||
if [ "${TARGET}" = "ALL" ]; then
|
||||
error_exit "Batch upgrade is unsupported."
|
||||
fi
|
||||
bastille_root_check
|
||||
|
||||
if [ -f "/bin/midnightbsd-version" ]; then
|
||||
echo -e "${COLOR_RED}Not yet supported on MidnightBSD.${COLOR_RESET}"
|
||||
@@ -86,45 +109,64 @@ arch_check() {
|
||||
|
||||
jail_check() {
|
||||
# Check if the jail is thick and is running
|
||||
if [ ! "$(/usr/sbin/jls name | awk "/^${TARGET}$/")" ]; then
|
||||
error_exit "[${TARGET}]: Not started. See 'bastille start ${TARGET}'."
|
||||
else
|
||||
if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then
|
||||
error_exit "${TARGET} is not a thick container."
|
||||
fi
|
||||
set_target_single "${TARGET}"
|
||||
check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then
|
||||
bastille start "${TARGET}"
|
||||
else
|
||||
error_notify "Jail is not running."
|
||||
error_continue "Use [-a|--auto] to auto-start the jail."
|
||||
fi
|
||||
if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then
|
||||
error_notify "${TARGET} is not a thick container."
|
||||
error_exit "See 'bastille update RELEASE' to update thin jails."
|
||||
fi
|
||||
}
|
||||
|
||||
jail_update() {
|
||||
local _jailname="${1}"
|
||||
local _jailpath="${bastille_jailsdir}/${TARGET}/root"
|
||||
local _freebsd_update_conf="${_jailpath}/etc/freebsd-update.conf"
|
||||
local _workdir="${_jailpath}/var/db/freebsd-update"
|
||||
# Update a thick container
|
||||
if [ -d "${bastille_jailsdir}/${TARGET}" ]; then
|
||||
jail_check
|
||||
if [ -d "${bastille_jailsdir}/${TARGET}" ]; then
|
||||
CURRENT_VERSION=$(/usr/sbin/jexec -l "${TARGET}" freebsd-version 2>/dev/null)
|
||||
if [ -z "${CURRENT_VERSION}" ]; then
|
||||
error_exit "Can't determine '${TARGET}' version."
|
||||
else
|
||||
env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_jailsdir}/${TARGET}/root" \
|
||||
fetch install --currently-running "${CURRENT_VERSION}"
|
||||
env PAGER="/bin/cat" freebsd-update ${OPTION} \
|
||||
--not-running-from-cron \
|
||||
-j "${_jailname}" \
|
||||
-d "${_workdir}" \
|
||||
-f "${_freebsd_update_conf}" \
|
||||
fetch install
|
||||
fi
|
||||
else
|
||||
error_exit "${TARGET} not found. See 'bastille bootstrap'."
|
||||
fi
|
||||
}
|
||||
|
||||
release_update() {
|
||||
local _releasepath="${bastille_releasesdir}/${TARGET}"
|
||||
local _freebsd_update_conf="${_releasepath}/etc/freebsd-update.conf"
|
||||
local _workdir="${_releasepath}/var/db/freebsd-update"
|
||||
# Update a release base(affects child containers)
|
||||
if [ -d "${bastille_releasesdir}/${TARGET}" ]; then
|
||||
if [ -d "${_releasepath}" ]; then
|
||||
TARGET_TRIM="${TARGET}"
|
||||
if [ -n "${ARCH_I386}" ]; then
|
||||
TARGET_TRIM=$(echo "${TARGET}" | sed 's/-i386//')
|
||||
fi
|
||||
|
||||
env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" \
|
||||
env PAGER="/bin/cat" freebsd-update ${OPTION} \
|
||||
--not-running-from-cron \
|
||||
-b "${_releasepath}" \
|
||||
-d "${_workdir}" \
|
||||
-f "${_freebsd_update_conf}" \
|
||||
fetch --currently-running "${TARGET_TRIM}"
|
||||
env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" \
|
||||
env PAGER="/bin/cat" freebsd-update ${OPTION} \
|
||||
--not-running-from-cron \
|
||||
-b "${_releasepath}" \
|
||||
-d "${_workdir}" \
|
||||
-f "${_freebsd_update_conf}" \
|
||||
install --currently-running "${TARGET_TRIM}"
|
||||
else
|
||||
error_exit "${TARGET} not found. See 'bastille bootstrap'."
|
||||
error_exit "${TARGET} not found. See 'bastille bootstrap RELEASE'."
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -145,10 +187,10 @@ template_update() {
|
||||
templates_update() {
|
||||
# Update all templates
|
||||
_updated_templates=0
|
||||
if [ -d "${bastille_templatesdir}" ]; then
|
||||
# shellcheck disable=SC2045
|
||||
for _template_path in $(ls -d "${bastille_templatesdir}"/*/*); do
|
||||
if [ -d "$_template_path"/.git ]; then
|
||||
if [ -d ${bastille_templatesdir} ]; then
|
||||
# shellcheck disable=SC2045
|
||||
for _template_path in $(ls -d ${bastille_templatesdir}/*/*); do
|
||||
if [ -d $_template_path/.git ]; then
|
||||
BASTILLE_TEMPLATE=$(echo "$_template_path" | awk -F / '{ print $(NF-1) "/" $NF }')
|
||||
template_update
|
||||
|
||||
@@ -174,5 +216,6 @@ elif echo "${TARGET}" | grep -q "[0-9]\{2\}.[0-9]-RELEASE"; then
|
||||
arch_check
|
||||
release_update
|
||||
else
|
||||
jail_update
|
||||
jail_check
|
||||
jail_update "${TARGET}"
|
||||
fi
|
||||
|
||||
@@ -34,31 +34,64 @@
|
||||
. /usr/local/etc/bastille/bastille.conf
|
||||
|
||||
usage() {
|
||||
error_exit "Usage: bastille upgrade release newrelease | target newrelease | target install | [force]"
|
||||
error_notify "Usage: bastille upgrade [option(s)] TARGET [NEWRELEASE|install]"
|
||||
cat << EOF
|
||||
Options:
|
||||
|
||||
-a | --auto Auto mode. Start/stop jail(s) if required.
|
||||
-f | --force Force upgrade a release.
|
||||
-x | --debug Enable debug mode.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Handle special-case commands first.
|
||||
case "$1" in
|
||||
help|-h|--help)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
# Handle options.
|
||||
OPTION=""
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|--help|help)
|
||||
usage
|
||||
;;
|
||||
-a|--auto)
|
||||
AUTO=1
|
||||
shift
|
||||
;;
|
||||
-f|--force)
|
||||
OPTION="-F"
|
||||
shift
|
||||
;;
|
||||
-x|--debug)
|
||||
enable_debug
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do
|
||||
case ${_opt} in
|
||||
a) AUTO=1 ;;
|
||||
f) OPTION="-F" ;;
|
||||
x) enable_debug ;;
|
||||
*) error_exit "Unknown Option: \"${1}\"" ;;
|
||||
esac
|
||||
done
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $# -gt 3 ] || [ $# -lt 2 ]; then
|
||||
if [ $# -lt 2 ] || [ $# -gt 3 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
TARGET="${1}"
|
||||
NEWRELEASE="${2}"
|
||||
|
||||
bastille_root_check
|
||||
|
||||
TARGET="$1"
|
||||
NEWRELEASE="$2"
|
||||
OPTION="$3"
|
||||
|
||||
# Check for unsupported actions
|
||||
if [ "${TARGET}" = "ALL" ]; then
|
||||
error_exit "Batch upgrade is unsupported."
|
||||
fi
|
||||
|
||||
# Check for unsupported actions
|
||||
if [ -f "/bin/midnightbsd-version" ]; then
|
||||
echo -e "${COLOR_RED}Not yet supported on MidnightBSD.${COLOR_RESET}"
|
||||
exit 1
|
||||
@@ -68,24 +101,14 @@ if freebsd-version | grep -qi HBSD; then
|
||||
error_exit "Not yet supported on HardenedBSD."
|
||||
fi
|
||||
|
||||
# Handle options
|
||||
case "${OPTION}" in
|
||||
-f|--force)
|
||||
OPTION="-F"
|
||||
;;
|
||||
*)
|
||||
OPTION=
|
||||
;;
|
||||
esac
|
||||
|
||||
jail_check() {
|
||||
# Check if the jail is thick and is running
|
||||
if [ ! "$(/usr/sbin/jls name | awk "/^${TARGET}$/")" ]; then
|
||||
error_exit "[${TARGET}]: Not started. See 'bastille start ${TARGET}'."
|
||||
else
|
||||
if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then
|
||||
error_exit "${TARGET} is not a thick container."
|
||||
fi
|
||||
set_target_single "${TARGET}"
|
||||
check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then
|
||||
bastille start "${TARGET}"
|
||||
else
|
||||
error_notify "Jail is not running."
|
||||
error_continue "Use [-a|--auto] to auto-start the jail."
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -96,60 +119,64 @@ release_check() {
|
||||
fi
|
||||
}
|
||||
|
||||
release_upgrade() {
|
||||
# Upgrade a release
|
||||
if [ -d "${bastille_releasesdir}/${TARGET}" ]; then
|
||||
release_check
|
||||
env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" --currently-running "${TARGET}" -r "${NEWRELEASE}" upgrade
|
||||
echo
|
||||
echo -e "${COLOR_YELLOW}Please run 'bastille upgrade ${TARGET} install' to finish installing updates.${COLOR_RESET}"
|
||||
else
|
||||
error_exit "${TARGET} not found. See 'bastille bootstrap'."
|
||||
fi
|
||||
}
|
||||
|
||||
jail_upgrade() {
|
||||
# Upgrade a thick container
|
||||
if [ -d "${bastille_jailsdir}/${TARGET}" ]; then
|
||||
jail_check
|
||||
release_check
|
||||
CURRENT_VERSION=$(jexec -l ${TARGET} freebsd-version)
|
||||
env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_jailsdir}/${TARGET}/root" --currently-running "${CURRENT_VERSION}" -r ${NEWRELEASE} upgrade
|
||||
echo
|
||||
echo -e "${COLOR_YELLOW}Please run 'bastille upgrade ${TARGET} install' to finish installing updates.${COLOR_RESET}"
|
||||
local _jailname="${1}"
|
||||
local _oldrelease="$(jexec -l ${TARGET} freebsd-version)"
|
||||
local _newrelease="${2}"
|
||||
local _jailpath="${bastille_jailsdir}/${TARGET}/root"
|
||||
local _workdir="${_jailpath}/var/db/freebsd-update"
|
||||
local _freebsd_update_conf="${_jailpath}/etc/freebsd-update.conf"
|
||||
|
||||
jail_check
|
||||
release_check
|
||||
|
||||
# Upgrade a thin jail
|
||||
if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then
|
||||
local _oldrelease="$(grep osrelease ${bastille_jailsdir}/${TARGET}/jail.conf | awk -F"= " '{print $2}' | sed 's/;//g')"
|
||||
local _newrelease="${NEWRELEASE}"
|
||||
# Update "osrelease" entry inside jail.conf
|
||||
sed -i '' "/.bastille/ s|${_oldrelease}|${_newrelease}|g" "${bastille_jailsdir}/${TARGET}/fstab"
|
||||
# Update "fstab" entry
|
||||
sed -i '' "/osrelease/ s|${_oldrelease}|${_newrelease}|g" "${bastille_jailsdir}/${TARGET}/jail.conf"
|
||||
info "Upgraded ${TARGET}: ${_oldrelease} -> ${_newrelease}"
|
||||
info "See 'bastille etcupdate TARGET' to update /etc/rc.conf"
|
||||
else
|
||||
error_exit "${TARGET} not found. See 'bastille bootstrap'."
|
||||
# Upgrade a thick jail
|
||||
env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron \
|
||||
--currently-running "${_oldrelease}" \
|
||||
-j "${_jailname}" \
|
||||
-d "${_workdir}" \
|
||||
-f "${_freebsd_update_conf}" \
|
||||
-r "${_newrelease}" upgrade
|
||||
|
||||
# Update "osrelease" entry inside jail.conf
|
||||
sed -i '' "/osrelease/ s|${_oldrelease}|${_newrelease}|g" "${bastille_jailsdir}/${TARGET}/jail.conf"
|
||||
echo
|
||||
echo -e "${COLOR_YELLOW}Please run 'bastille upgrade ${TARGET} install', restart the jail, then run 'bastille upgrade ${TARGET} install' again to finish installing updates.${COLOR_RESET}"
|
||||
fi
|
||||
}
|
||||
|
||||
jail_updates_install() {
|
||||
local _jailname="${1}"
|
||||
local _jailpath="${bastille_jailsdir}/${TARGET}/root"
|
||||
local _workdir="${_jailpath}/var/db/freebsd-update"
|
||||
local _freebsd_update_conf="${_jailpath}/etc/freebsd-update.conf"
|
||||
# Finish installing upgrade on a thick container
|
||||
if [ -d "${bastille_jailsdir}/${TARGET}" ]; then
|
||||
jail_check
|
||||
env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_jailsdir}/${TARGET}/root" install
|
||||
env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron \
|
||||
-j "${_jailname}" \
|
||||
-d "${_workdir}" \
|
||||
-f "${_freebsd_update_conf}" \
|
||||
install
|
||||
else
|
||||
error_exit "${TARGET} not found. See 'bastille bootstrap'."
|
||||
fi
|
||||
}
|
||||
|
||||
release_updates_install() {
|
||||
# Finish installing upgrade on a release
|
||||
if [ -d "${bastille_releasesdir}/${TARGET}" ]; then
|
||||
env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron -b "${bastille_releasesdir}/${TARGET}" install
|
||||
else
|
||||
error_exit "${TARGET} not found. See 'bastille bootstrap'."
|
||||
error_exit "${TARGET} not found. See 'bastille bootstrap RELEASE'."
|
||||
fi
|
||||
}
|
||||
|
||||
# Check what we should upgrade
|
||||
if echo "${TARGET}" | grep -q "[0-9]\{2\}.[0-9]-RELEASE"; then
|
||||
if [ "${NEWRELEASE}" = "install" ]; then
|
||||
release_updates_install
|
||||
else
|
||||
release_upgrade
|
||||
fi
|
||||
elif [ "${NEWRELEASE}" = "install" ]; then
|
||||
jail_updates_install
|
||||
if [ "${NEWRELEASE}" = "install" ]; then
|
||||
jail_updates_install "${TARGET}"
|
||||
else
|
||||
jail_upgrade
|
||||
jail_upgrade "${TARGET}" "${NEWRELEASE}"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user