commit 8ba54c36ebbf4a3f09d965fe4f368985ec0b77a7 Author: Aaron Bieber Date: Mon Sep 23 18:13:18 2019 -0600 initial bits for boxctl diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cc8f706 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019 Aaron Bieber + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..987a3b7 --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +# $OpenBSD$ + +PREFIX ?= /usr/local +SCRIPT = boxctl.sh +MAN = man/boxctl.8 +MANDIR ?= ${PREFIX}/man/man +BINDIR ?= ${PREFIX}/bin + +README.md: man/boxctl.8 + mandoc -T lint man/boxctl.8 + mandoc -T markdown man/boxctl.8 >$@ + +sign: + @sha256 boxctl.sh > SHA256 + @signify -S -s ~/signify/boxctl.sec -m SHA256 -x SHA256.sig + @cat SHA256 >> SHA256.sig + +verify: + @signify -C -p /etc/signify/boxctl.pub -x SHA256.sig boxctl.sh + +realinstall: + ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ + ${.CURDIR}/${SCRIPT} ${DESTDIR}${BINDIR}/boxctl + +.PHONY: verify sign + +.include diff --git a/README.md b/README.md new file mode 100644 index 0000000..1efeafa --- /dev/null +++ b/README.md @@ -0,0 +1,117 @@ +BOXCTL(8) - System Manager's Manual + +# NAME + +**boxctl** - tool to manage remote +OpenBSD +machines + +# SYNOPSIS + +**boxctl** +\[**-mnv**] +\[**-h** *host*] +\[**-u** *user*] + +# DESCRIPTION + +**boxctl** +is a +ksh(1) +script designed to help manage +OpenBSD +machines. +It uses only tools contained in +OpenBSD +base. + +The options are as follows: + +**-h** *host* + +> Remote host to be managed. + +**-u** *user* + +> User to connect to +> *host* +> with. +> Defaults to +> *root*. + +**-m** + +> Run maintenance tasks. +> This includes deleting unused dependencies using +> pkg\_delete(1). +> And installing / updating firmware using +> fw\_update(1). + +**-n** + +> Dry run. +> This will only print the commands that will be run. + +**-v** + +> Increase verbosity. +> More v's can be specified to increase information output. +> The number of v's are passed to tools used by +> **boxctl**. + +# FILES + +*$CWD/files* + +> Is a ":" delimited index of source file, owner, group, mode and destination. +> Each source will be copied to the specified destination, then chown/chmod will +> be run with the values specified. +> If this file does not exist, no files are copied. + +*$CWD/services* + +> An optional file that contains a list of services to enable on the remote +> host. +> If a service is already enabled, it will be restarted each run of +> **boxctl**. + +*$CWD/packages* + +> When this file exists, +> **boxctl** +> will install the packages contained therewithin on the remote host. +> A list is cached on the remote host under /etc/packages. +> This list (if it exists) will be compared using +> diff(1) +> and only missing packages will be installed. +> Package names should be listed by their fuzzy names. +> See +> pkg\_info(1) +> for more information on fuzzy names. + +# SEE ALSO + +chmod(1), +diff(1), +fw\_update(1), +pkg\_add(1), +pkg\_delete(1), +pkg\_info(1), +scp(1), +ssh(1), +chown(8), +rcctl(8) + +# HISTORY + +The first version of +**boxctl** +was released in September of 2019. + +# AUTHORS + +**boxctl** +was written by +Aaron Bieber <[aaron@bolddaemon.com](mailto:aaron@bolddaemon.com)>. + +OpenBSD 6.6 - September 23, 2019 diff --git a/boxctl.sh b/boxctl.sh new file mode 100755 index 0000000..136b764 --- /dev/null +++ b/boxctl.sh @@ -0,0 +1,198 @@ +#!/bin/ksh + +# /* +# * Copyright (c) 2019 Aaron Bieber +# * +# * Permission to use, copy, modify, and distribute this software for any +# * purpose with or without fee is hereby granted, provided that the above +# * copyright notice and this permission notice appear in all copies. +# * +# * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# */ + +set -au + +SERVER="" +RUN_USER="root" +VERBOSITY=0 +DRY=0 +MAINTENANCE=0 +SSH_CTL_PATH="/tmp/boxctl-%r@%h:%p" +SSH_OPTS="-o ControlMaster=auto -o ControlPersist=60s -o ControlPath=${SSH_CTL_PATH}" +SERVICE_START_RESTART=$(cat < /tmp/new_packages + /usr/sbin/pkg_add %s -z -l /tmp/new_packages +else + /usr/sbin/pkg_add %s -z -l /etc/packages.tmp +fi +mv /etc/packages.tmp /etc/packages +EOF +) + +while getopts "h:u:nv" arg; do + case $arg in + h) + SERVER=$OPTARG + ;; + v) + VERBOSITY=$((VERBOSITY+1)) + ;; + n) + DRY=1 + ;; + u) + RUN_USER=$OPTARG + ;; + m) + MAINTENANCE=1 + ;; + esac +done + +msg() { + local _level _msg + _level=$1 + _msg=$2 + if [ $VERBOSITY -ge $_level ] && [ $DRY == 0 ]; then + echo "==> $_msg" + fi +} + +expand_v() { + V="" + if [ $VERBOSITY -gt 0 ]; then + for v in $(jot $VERBOSITY); do + V="${V}v" + done + fi + if [ "${V}" == "" ]; then + echo "${V}" + else + echo "-${V}" + fi +} + +ssh_verbose() { + local _opt="" + if [ $VERBOSITY -ge 4 ]; then + _opt="$V" + fi + + if [ $DRY == 1 ]; then + echo ssh ${SSH_OPTS} $_opt "$1" "${2}" + else + ssh ${SSH_OPTS} $_opt "$1" "${2}" + fi +} + +ssh_quiet() { + if [ $DRY == 1 ]; then + echo "ssh ${SSH_OPTS} '$1' '${2}' >/dev/null" + else + ssh ${SSH_OPTS} "$1" "${2}" >/dev/null + fi +} + +scp_verbose() { + local _opt="" + if [ $VERBOSITY -ge 4 ]; then + _opt="$V" + fi + + if [ $DRY == 1 ]; then + echo scp ${SSH_OPTS} $_opt "$1" "${2}" + else + scp ${SSH_OPTS} $_opt "$1" "${2}" + fi +} + +scp_quiet() { + if [ $DRY == 1 ]; then + echo "scp ${SSH_OPTS} '$1' '${2}' >/dev/null" + else + scp ${SSH_OPTS} "$1" "${2}" >/dev/null + fi +} + + +_scp() { + local _src _dest + _src=$1 + _dest=$2 + + if [ $VERBOSITY -gt 2 ]; then + scp_verbose "$_src" "$_dest" + else + scp_quiet "$_src" "$_dest" + fi +} + +_ssh() { + local _server _cmd + _server=$1 + _cmd=$2 + + if [ $VERBOSITY -gt 2 ]; then + ssh_verbose "$_server" "$_cmd" + else + ssh_quiet "$_server" "$_cmd" + fi +} + +V=$(expand_v) + +if [ -f ./files ]; then + msg 0 "Installing files" + for file in $(cat files); do + local _src _dest _mode _owner _group + read _src _owner _group _mode _dest < ${_dest}" + msg 2 "\t\tchown ${_owner}:${_group} $_dest" + msg 2 "\t\tchmod ${_mode} $_dest" + + _scp $_src "${RUN_USER}@${SERVER}:$_dest" + _ssh ${RUN_USER}@${SERVER} "/sbin/chown ${_owner}:${_group} $_dest; \ + /bin/chmod ${_mode} $_dest" + done +fi + +if [ -f ./services ]; then + msg 0 "Enabling services" + for service in $(cat services); do + msg 1 "\tenabling/restarting ${service}" + cmd="$(printf "$SERVICE_START_RESTART" \ + $service $service $service $service)" + _ssh ${RUN_USER}@${SERVER} "${cmd}" + done +fi + +if [ -f ./packages ]; then + msg 0 "Installing $(wc -l packages | awk '{print $1 " " $2}') on ${SERVER}" + cmd=$(printf "${PKG_DIFF_INSTALL}" $V $V) + _scp packages "${RUN_USER}@${SERVER}:/etc/packages.tmp" + _ssh ${RUN_USER}@${SERVER} "${cmd}" +fi + +if [ $MAINTENANCE == 1 ]; then + msg 0 "Cleaning up unused packages" + _ssh ${RUN_USER}@${SERVER} "/usr/sbin/pkg_delete -a" +fi diff --git a/man/boxctl.8 b/man/boxctl.8 new file mode 100644 index 0000000..f000c4b --- /dev/null +++ b/man/boxctl.8 @@ -0,0 +1,110 @@ +.\" $OpenBSD$ +.\" +.\" Copyright (c) 2019 Aaron Bieber +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: September 23 2019 $ +.Dt BOXCTL 8 +.Os +.Sh NAME +.Nm boxctl +.Nd tool to manage remote +.Ox +machines +.Sh SYNOPSIS +.Nm boxctl +.Op Fl mnv +.Op Fl h Ar host +.Op Fl u Ar user +.Sh DESCRIPTION +.Nm +is a +.Xr ksh 1 +script designed to help manage +.Ox +machines. +It uses only tools contained in +.Ox +base. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl h Ar host +Remote host to be managed. +.It Fl u Ar user +User to connect to +.Pa host +with. +Defaults to +.Pa root . +.It Fl m +Run maintenance tasks. +This includes deleting unused dependencies using +.Xr pkg_delete 1 . +And installing / updating firmware using +.Xr fw_update 1 . +.It Fl n +Dry run. +This will only print the commands that will be run. +.It Fl v +Increase verbosity. +More v's can be specified to increase information output. +The number of v's are passed to tools used by +.Nm . +.El +.Sh FILES +.Bl -tag -width $CWD/packages +.It Pa $CWD/files +Is a ":" delimited index of source file, owner, group, mode and destination. +Each source will be copied to the specified destination, then chown/chmod will +be run with the values specified. +If this file does not exist, no files are copied. +.It Pa $CWD/services +An optional file that contains a list of services to enable on the remote +host. +If a service is already enabled, it will be restarted each run of +.Nm . +.It Pa $CWD/packages +When this file exists, +.Nm +will install the packages contained therewithin on the remote host. +A list is cached on the remote host under /etc/packages. +This list (if it exists) will be compared using +.Xr diff 1 +and only missing packages will be installed. +Package names should be listed by their fuzzy names. +See +.Xr pkg_info 1 +for more information on fuzzy names. +.El +.Sh SEE ALSO +.Xr chmod 1 , +.Xr diff 1 , +.Xr fw_update 1 , +.Xr pkg_add 1 , +.Xr pkg_delete 1 , +.Xr pkg_info 1 , +.Xr scp 1 , +.Xr ssh 1 , +.Xr chown 8 , +.Xr rcctl 8 +.Sh HISTORY +The first version of +.Nm +was released in September of 2019. +.Sh AUTHORS +.An -nosplit +.Nm +was written by +.An Aaron Bieber Aq Mt aaron@bolddaemon.com .